Game.Simulation.BrandPopularitySystem
Assembly: Assembly-CSharp
Namespace: Game.Simulation
Type: class BrandPopularitySystem
Base: GameSystemBase, IPreDeserialize
Summary:
Tracks and exposes brand popularity by counting how many company-branded properties are currently rented (and not under construction). The system builds a sorted NativeList
Nested Types
public struct BrandPopularity
- Fields:
Entity m_BrandPrefab
— the brand prefab/entity used as the key.int m_Popularity
— the computed count of active rented properties for this brand.
- Implements IComparable
with CompareTo ordering so that sorting places higher popularity first.
Summary: Represents a single brand and its popularity count. Used as the element type of the persistent NativeList maintained by the system.
[BurstCompile] private struct UpdateBrandPopularityJob : IJob
- Inputs:
NativeList<ArchetypeChunk> m_CompanyChunks
(ReadOnly) — chunks of entities matching CompanyData + PropertyRenter.ComponentTypeHandle<CompanyData> m_CompanyDataType
(ReadOnly)ComponentTypeHandle<PropertyRenter> m_CompanyRentPropertyType
(ReadOnly)ComponentLookup<UnderConstruction> m_UnderConstructions
(ReadOnly)
- Output / scratch:
NativeList<BrandPopularity> m_BrandPopularity
— the list to populate and sort.
- Behavior summary:
- Clears m_BrandPopularity.
- Iterates company chunks and for each CompanyData + PropertyRenter pair:
- If company has a brand (m_Brand != Entity.Null), the property exists (m_Property != Entity.Null), and the property is not under construction, increments a map counter for that brand.
- Adds a BrandPopularity entry for each distinct brand it encounters.
- Writes the counts back into m_BrandPopularity and sorts the list (most popular first).
- Uses a NativeParallelHashMap locally allocated with Allocator.Temp to accumulate counts; disposes it before finishing.
-
Notes:
- Burst-compatible and scheduled asynchronously.
- Uses Allocator.Temp for the hash map — fine for short-lived work inside the job.
-
private struct TypeHandle
- Holds cached component type handles and a method __AssignHandles to populate them from a SystemState. Used to avoid repeated GetComponentTypeHandle/GetComponentLookup calls each frame.
Fields
-
private EntityQuery m_ModifiedQuery
Description: EntityQuery selecting entities that have CompanyData and PropertyRenter and are not Deleted or Temp. The query is required for update (RequireForUpdate) so the system only runs when there are matching entities. -
private NativeList<BrandPopularity> m_BrandPopularity
Description: Persistent NativeList that holds the sorted brand popularity results. Allocated with Allocator.Persistent in OnCreate and disposed in OnDestroy. Consumers must respect job dependencies returned by ReadBrandPopularity before reading its contents on the main thread. -
private JobHandle m_Readers
Description: Tracks job dependencies from readers (currently not used beyond being reset to default on update). The system combines its scheduled job with existing dependencies when scheduling. -
public const int kUpdatesPerDay = 128
Description: Constant value present in the class source. Not used directly in the system’s logic, but likely represents intended frequency/heuristic for gameplay logic (kept for reference). -
private TypeHandle __TypeHandle
Description: Internal cached ComponentTypeHandle/ComponentLookup holders used by the system to access components in jobs.
Properties
This system exposes no public C# properties. The primary consumer-facing API is ReadBrandPopularity(out JobHandle).
Constructors
public BrandPopularitySystem()
Description: Default constructor (preserved). Standard system construction — actual initialization is performed in OnCreate.
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase)
Returns: int
Description: Returns the update interval used by the underlying system scheduler. This implementation returns 2048 (the system will be scheduled accordingly by the engine's update loop). -
[Preserve] protected override void OnCreate()
Description: - Initializes m_ModifiedQuery to select CompanyData + PropertyRenter while excluding Deleted and Temp.
- Allocates m_BrandPopularity = new NativeList
(Allocator.Persistent). - Calls RequireForUpdate(m_ModifiedQuery) so the system only runs when matching entities exist.
-
Ensures TypeHandle will be assigned during compiler-specific initialization path.
-
public void PreDeserialize(Context context)
Description: Implementation of IPreDeserialize. Clears m_BrandPopularity to prevent stale data from persisting across serialization boundaries. -
[Preserve] protected override void OnDestroy()
Description: Disposes the persistent m_BrandPopularity and then calls base.OnDestroy(). -
[Preserve] protected override void OnUpdate()
Description: - Builds an asynchronous list of archetype chunks from m_ModifiedQuery (ToArchetypeChunkListAsync).
- Schedules UpdateBrandPopularityJob passing in the chunk list, cached component handles, and the persistent m_BrandPopularity.
- Combines dependencies (base.Dependency, chunk list handle, and m_Readers) to produce the job's dependency and assigns it to base.Dependency.
- Disposes the temporary chunk list with a job handle for proper synchronization.
- Resets m_Readers to default. Notes:
-
The job populates and sorts the persistent NativeList. Consumers must synchronize using the dependency returned by ReadBrandPopularity before accessing the list on the main thread.
-
public NativeList<BrandPopularity> ReadBrandPopularity(out JobHandle dependency)
Returns: NativeList
Description: - Returns the internal persistent NativeList containing the most recently computed brand popularity values.
- Outputs 'dependency' which is the system's current base.Dependency. Consumers should Complete() that dependency before reading the list on the main thread to ensure the data is ready and no race occurs.
-
The returned NativeList is owned by the system; callers must not Dispose it.
-
private void __AssignQueries(ref SystemState state)
Description: Compiler helper that may set up additional queries; currently creates and disposes an EntityQueryBuilder(Allocator.Temp) as part of system construction path. -
protected override void OnCreateForCompiler()
Description: Compiler-time initialization helper. Calls __AssignQueries and __TypeHandle.__AssignHandles to populate cached handles for runtime use.
Usage Notes and Modding Tips
- Synchronization: After calling ReadBrandPopularity(out JobHandle dep) you must ensure dep.Complete() (or otherwise include dep in further job dependencies) before iterating or reading values on the main thread.
- Memory: m_BrandPopularity is allocated with Allocator.Persistent and disposed by the system in OnDestroy. Do not dispose it yourself.
- Lifetime: The system clears m_BrandPopularity in PreDeserialize to avoid stale entries during load. If you rely on brand popularity across load/save boundaries, read/refresh the list after load.
- Performance: The heavy work is performed in a Burst-compiled IJob. The job uses a temporary NativeParallelHashMap (Allocator.Temp) and NativeList operations. This is intended for short-lived processing each update interval. The system’s GetUpdateInterval returns 2048 — if you need more or less frequent updates, adjust via system override (careful with performance).
- Thread-safety: Do not access m_BrandPopularity while the system's dependency is not completed. Use the returned JobHandle from ReadBrandPopularity when composing your own jobs to safely read the list without forcing main-thread blocking.
Usage Example
// Example consumer that reads the brand popularity safely from another system or MonoBehaviour:
public void UseBrandPopularity(BrandPopularitySystem brandSystem)
{
JobHandle dependency;
var list = brandSystem.ReadBrandPopularity(out dependency);
// Ensure the job that populates the list has finished before reading on the main thread:
dependency.Complete();
// Iterate the results (list is owned by the system; do not dispose):
for (int i = 0; i < list.Length; i++)
{
var entry = list[i];
Entity brand = entry.m_BrandPrefab;
int popularity = entry.m_Popularity;
// Use brand and popularity (e.g., present UI or make decisions)
}
}
If you need to process the popularity list in another job, pass the 'dependency' returned by ReadBrandPopularity into your job scheduling to maintain proper ordering without blocking the main thread.