Game.Simulation.LookForPartnerSystem
Assembly: Game (Assembly-CSharp)
Namespace: Game.Simulation
Type: class
Base: GameSystemBase
Summary:
LookForPartnerSystem is an ECS system that selects individual citizens who will "look for a partner" and enqueues them into a global LookingForPartner buffer. It runs in multiple update slices per in-game day (kUpdatesPerDay = 4) and uses burst-compiled jobs (LookForPartnerJob and AddPartnerSeekerJob) to scan citizens, apply probabilistic rules (based on CitizenParametersData and per-citizen pseudo-random), add a LookingForPartner entry to a persistent NativeQueue, and then flush that queue into a shared LookingForPartner dynamic buffer. The system skips children/teens, dead citizens, tourists/commuters, and households that are not moved in. It also exposes a debug NativeValue
Fields
-
public static readonly int kUpdatesPerDay
Constant indicating how many updates per in-game day this system divides work into (value 4). Used to compute the update frame index. -
private SimulationSystem m_SimulationSystem
Reference to the SimulationSystem used to compute the update frame (frameIndex). -
private EntityQuery m_CitizenQuery
EntityQuery selecting citizens used to drive scheduling/RequireForUpdate. -
private EntityQuery m_LookingQuery
EntityQuery used to find the singleton entity which holds the LookingForPartner buffer. -
private EntityQuery m_CitizenParametersQuery
EntityQuery used to fetch CitizenParametersData singleton (contains rates for looking for partners). -
private NativeQueue<LookingForPartner> m_Queue
Persistent NativeQueue used as a temporary staging area to collect new LookingForPartner entries from parallel jobs, later flushed into the shared dynamic buffer by AddPartnerSeekerJob. -
[DebugWatchValue] private NativeValue<int> m_DebugLookingForPartner
Persistent single-value container used for debugging; written with the count of queued partner seekers when the queue is flushed. -
private TypeHandle __TypeHandle
Internal struct holding component/handle types used for job scheduling (EntityTypeHandle, SharedComponentTypeHandle, ComponentTypeHandles, BufferLookups, etc). -
(Nested types)
AddPartnerSeekerJob
,LookForPartnerJob
,TypeHandle
Nested structs used for job logic and handle assignment. See Methods and summary for their responsibilities.
Properties
- (none)
This system does not expose public properties.
Constructors
public LookForPartnerSystem()
Default constructor (empty). System initialization happens in OnCreate.
Methods
-
public override int GetUpdateInterval(SystemUpdatePhase phase) : int
Returns the system update interval used by the framework. Implementation returns262144 / (kUpdatesPerDay * 16)
. This controls how often the system will be considered for update relative to the engine's tick schedule. -
[Preserve] protected override void OnCreate() : void
Creates persistent native containers and sets up queries: - Allocates m_DebugLookingForPartner (Allocator.Persistent).
- Gets/creates SimulationSystem reference.
- Builds queries for citizens, LookingForPartner, and CitizenParametersData.
- Allocates m_Queue (Allocator.Persistent).
-
Calls RequireForUpdate on m_CitizenQuery and m_CitizenParametersQuery so the system only runs when those exist.
-
[Preserve] protected override void OnDestroy() : void
Disposes persistent native containers: -
Disposes m_Queue and m_DebugLookingForPartner.
-
[Preserve] protected override void OnUpdate() : void
Schedules and executes the main work: - Computes the current update frame index using SimulationUtils.GetUpdateFrame with m_SimulationSystem.frameIndex and kUpdatesPerDay.
- Prepares and schedules a Burst-compiled LookForPartnerJob in parallel across m_CitizenQuery. LookForPartnerJob:
- Iterates citizens in each chunk and filters by update frame shard (shared component UpdateFrame).
- Skips children/teens, citizens already looking for partner, or dead citizens.
- Skips households that are tourists/commuters, not moved in, or missing household-citizen buffer.
- Counts adult/elderly members of the household; if less than 2 and a random check passes (m_LookForPartnerRate), enqueues a LookingForPartner entry into the NativeQueue and marks the citizen flag m_State |= CitizenFlags.LookingForPartner.
- Uses per-citizen pseudo-random to determine partner type (Same, Other, Any) based on m_LookForPartnerTypeRate.
- Optionally writes to a debug queue if it is created.
- After scheduling the parallel job, schedules AddPartnerSeekerJob which:
- Writes the debug count to m_DebugLookingForPartner.
- Gets the singleton entity containing the LookingForPartner dynamic buffer and appends all queued LookingForPartner entries from m_Queue into that buffer.
-
The system uses m_Queue.AsParallelWriter() for the parallel enqueue and then reuses the same m_Queue instance to flush into the buffer on the main thread/job.
-
protected override void OnCreateForCompiler() : void
Internal initialization used by the compiled environment: -
Calls __AssignQueries and assigns type handles via __TypeHandle.__AssignHandles(ref base.CheckedStateRef).
-
private void __AssignQueries(ref SystemState state) : void
Internal stub used during compilation/build of queries. Here it creates and immediately disposes a temporary EntityQueryBuilder (no explicit queries assigned in this method in the current source). -
(Nested type)
LookForPartnerJob : IJobChunk
- Burst-compiled chunk job that inspects citizen chunks and enqueues LookingForPartner entries into a NativeQueue
. Main Execute signature: public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
- Important fields used by the job: m_EntityType, m_UpdateFrameType, m_HouseholdMemberType, m_HouseholdCitizens (BufferLookup), m_Citizens (ComponentLookup, read/write), m_HealthProblems, m_Tourists, m_Commuters, m_Households, m_Queue (ParallelWriter), m_RandomSeed, m_UpdateFrameIndex, m_CitizenParametersData, m_DebugLookForPartnerQueue.
-
Behavior described above in OnUpdate.
-
(Nested type)
AddPartnerSeekerJob : IJob
- Burst-compiled single-threaded job that drains the NativeQueue
and appends each entry into the dynamic buffer on the singleton LookingForPartner entity. -
Also writes the debug count into m_DebugLookingForPartner.
-
(Nested type)
TypeHandle
- Holds the various Unity ECS type handles and provides __AssignHandles(ref SystemState) to populate them before scheduling jobs.
Notes and important details:
- The system maintains m_Queue as a persistent NativeQueue. It uses AsParallelWriter for parallel enqueues and expects to be flushed every update by AddPartnerSeekerJob. m_Queue is disposed in OnDestroy.
- Citizen flags are modified in-place via ComponentLookup
Usage Example
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// Native containers are allocated by the system implementation.
// If you need to read the debug count (m_DebugLookingForPartner), you can
// either add a debug watch or obtain the system and read its debug field
// via reflection or by exposing an accessor in a modded variant.
}
Additional example (how the system schedules jobs internally — for reference):
// Compute update frame index
uint updateFrame = SimulationUtils.GetUpdateFrame(m_SimulationSystem.frameIndex, kUpdatesPerDay, 16);
// Prepare and schedule the chunk job (parallel)
var lookJob = new LookForPartnerJob {
m_EntityType = /* ... */,
m_UpdateFrameType = /* ... */,
m_Queue = m_Queue.AsParallelWriter(),
m_RandomSeed = RandomSeed.Next(),
m_UpdateFrameIndex = updateFrame,
m_CitizenParametersData = m_CitizenParametersQuery.GetSingleton<CitizenParametersData>(),
// other handles...
};
base.Dependency = JobChunkExtensions.ScheduleParallel(lookJob, m_CitizenQuery, base.Dependency);
// After parallel job, flush queue into the shared buffer
var addJob = new AddPartnerSeekerJob {
m_DebugLookingForPartner = m_DebugLookingForPartner,
m_LookingForPartners = /* buffer lookup */,
m_LookingForPartnerEntity = m_LookingQuery.GetSingletonEntity(),
m_Queue = m_Queue
};
base.Dependency = IJobExtensions.Schedule(addJob, base.Dependency);
If you intend to mod or extend this system: - Be careful with NativeQueue lifetimes and parallel writers. - Respect SharedComponent UpdateFrame sharding when adding chunk-based logic. - If you add additional flags or modify citizen state, ensure consistent read/write access via ComponentLookup and proper synchronization with jobs.