On the same stretch of sidewalk, ambient pedestrians retire as the observer moves away, while a pedestrian claimed by a script remains. Returning to the street creates a population shortfall. If the system reuses an earlier entity to fill it, that pedestrian must resume walking from a newly approved position. Population demand, entity identity, script ownership, and route state all participate in this process. Showing or hiding a character model cannot manage them on its own.
City Population Runtime, Part I: World Foundations, Population Scheduling, and Perception and Decision-Making examined how the world hosts entities and divides responsibility among population, intelligence, and tasks. This article follows those ideas into the UE5 prototype through spawning, activity, retirement, and readmission. Character–vehicle relationships build on Vehicle Driving Runtime in UE5. Service events and dispatch are downstream behavior; they do not establish another pedestrian lifecycle here.
The reel below shows population changes, script ownership, area protection, initialization during a fade, retirement and reuse, walking transitions, and three pedestrians passing. The runtime generates and advances the pedestrians. Recording scripts control the camera, operations, and captions rather than writing pedestrian coordinates.
Overview video: 65.2 seconds, assembling the main clips in article order. The reel is 1280×720 at 15 fps, with 978 frames. These are delivery sampling and encoding specifications, not UE runtime performance. Black frames in the fade sequence come from the actual camera feature. The clips are independent cases, not one continuous task involving the same pedestrians. Original video overlays remain untranslated.
This work covers admission, spatial retirement, script protection, reuse, and walking execution in a local street section. Complete city density, model streaming, scenario behavior, network population, and simplified/full pedestrian representation conversion remain incomplete. The article distinguishes reference mechanisms, current engineering adaptations, and tested scope. Visible behavior does not replace state checks in source and logs.
Implementation and acceptance claims in this article refer to the versions covered by this delivery package. Later working-tree changes do not automatically become conclusions supported by these videos.
What population, entities, and presentation each retain
Ped denotes a logical character entity, holding identity, ownership, events, tasks, and relationships. A skeletal visual proxy reads that state to present the character. Population membership records which pedestrians a source currently manages; a population target states how many it wants to maintain. Targets, membership counts, and the number of entities still queryable in the world need not always match.
For example, an occupied candidate can leave demand waiting without creating a hidden character in advance. When a pedestrian leaves active population for the reuse pool, membership decreases while the logical entity and original handle remain. A script claim removes a pedestrian from ambient counts without freeing its physical source capacity. Subsequent interfaces consume these intermediate states separately.
UE’s WorldSubsystem is the host. The world runtime owns entity identity, phased execution, and lifetime. Population scheduling handles demand, admission, membership, and retirement in its phase; tasks and routes own later activity. Scene Actors supply physics queries and presentation. Their individual Ticks do not replace world-level state authority.
| State | Principal owner | Retained information | What it does not establish |
|---|---|---|---|
| Population target and demand | Population manager | Target count, unfilled demand, source, and type | Demand does not mean an entity has spawned |
| Candidate and reservation | Spawn-admission process | Actual candidate position, route progress, and batch occupancy | Reservation does not mean world membership has been published |
| Active membership | Source record | Current pedestrian handle, source relationship, and generation | Retirement does not mean logical deletion |
| Ped entity | World and pedestrian | Identity, type, script ownership, tasks, events, and vehicle relationships | A valid handle does not mean updates are enabled |
| Reuse-pool entry | Population reuse manager | Original handle, type matching, source generation, quarantine frame, and restoration data | A pooled entity is not necessarily ready for acquisition |
| Route plan | Formal route executor | Destination, progress, completion, and current position-write authority | Diagnostic history does not establish an active route |
| Presentation and animation | UE visual proxy | Rendered position, orientation, gait, and pose | A walk animation does not establish logical displacement |
Contents
- What population, entities, and presentation each retain
- Check the actual position before spawning
- How population cycles allocate processing opportunities
- Retirement first checks whether another system still needs the pedestrian
- How script claims change ownership and population counts
- Non-creation and non-removal areas are independent
- Hidden initialization requires observed screen state
- Retirement into the pool retains the original handle
- Reuse stall: the old route interferes with readmission
- Animation reads movement rather than driving population
- Routes commit movement; avoidance only suggests steering
- What the tests check
- Continuing from a local lifecycle into the city
- AI collaboration retrospective
The reuse case makes this division concrete. Population can acquire an old entity while a route still considers itself authoritative over its position, preventing the new spawn position from taking effect. Locally valid records can still conflict during handover.
Follow the host API to the state writer
Start at the operation exposed by the UE host, then follow the request to the runtime that retains its state. The host resolves the current world, validates the entity handle, and forwards the request. Exposing a Blueprint function does not make it the shared owner of tasks, population, and position. The world scheduler runs population processing through its Control chain; source records then connect that work to the street block’s realization and route execution. Searching only for the call that creates a pedestrian misses admission before it and membership attachment after it.
These data also have different lifetimes. Camera matrices and fade amounts form an observation snapshot refreshed at the next Control update. Sources, pending demands, and entity handles persist across updates. An active route plan outlives a local steering suggestion. Keeping these states as temporary variables on one Actor would make Tick order an implicit contract: one consumer might read the new observation while another already reads changed membership.
The implementation constrains this at the relevant consumption boundaries. Population cycles read the spatial observation retained for the current Control update. Realization reads the established demand and source. Routes consume their valid plans, and presentation reads the resulting motion. This does not provide an atomic snapshot across every subsystem; withdrawal protection still needs checking at actual retirement. It makes the producer, lifetime, and permitted interpretation of each record explicit.
Diagnosis follows the same dependencies. Can the world still resolve the handle? Does the source still list the member? Is the demand pending? Has realization attached the entity? Does a route still own position writes? Has presentation received the new transform? A recovered population count answers only part of this sequence. The later reuse failure occurs after membership recovers but before position authority has been handed over correctly.
Check the actual position before spawning
Follow one spawn through the call order. Demand supplies a candidate. Admission checks that candidate, reserves it, then creates or reuses an entity. The tested position must be the position eventually used. Checking the middle of a route and initializing everyone at its start would invalidate the earlier visibility and occupancy checks.
Candidates retain route progress. Admission, batch reservations, and instance attachment use that progress, and the formal route keeps the approved position. In native spatial mode, new pedestrians no longer all return to route zero or traverse an extra staged approach used by the older entry path. Legacy callers retain their own handling; one branch’s behavior does not describe every caller.
Video 1: Population changes, 9.4 seconds. Moving the observer away reduces formal population from 2 to 0; returning restores it to 2 and walking continues. The street section stays loaded. A close-view spawning override is used, so visible distances do not establish the default spawn ranges.
Visibility comes from actual local views
District states such as Active, Warm, and Inactive describe regional execution policy. They do not answer whether a player can see a candidate. In the world Control phase, native spatial mode reads local views and retains projection matrices, camera positions, population centers, and fade observations. Population cycles share that snapshot rather than reading different camera states during the same update.
Frustum checks use actual UE local-player projection data and the candidate’s bounding sphere. Range generally uses horizontal distance from the candidate root to the population center. The close visible-candidate check also includes three-dimensional distance to the camera. This host prefers the player’s Pawn position for population control and uses camera position for visibility; those positions are not necessarily identical.
| Spawn condition | Current default range | Condition |
|---|---|---|
| Ordinary visible candidate | 90–130 m | Candidate bounding sphere intersects the actual frustum |
| Ordinary offscreen candidate | 50–75 m | Candidate is outside the view |
| Hidden-startup candidate | 1–30 m | A startup reason exists and all relevant valid local views satisfy the actual fade condition |
These ranges belong to the configuration branches covered here, not every pedestrian or scene. Most main clips use a 3–35 m filming override for closer observation. The fade-initialization clip preserves the normal and hidden ranges in the table. Separating filming settings from defaults prevents close spawning footage from being used to explain distant-generation rules.
Multiple local views also require protection against spawning in front of another viewer. The current check rejects a candidate that is too close to any valid view and requires it to fall within at least one observation’s allowed range. Missing valid views defer generation in native spatial mode. No observation is not evidence that a candidate is offscreen. Explicit legacy mode for viewless tools is excluded from actual-camera admission claims.
Query physical occupancy and logical pedestrians separately
Candidates also pass capsule occupancy, signal-conflict, and batch-reservation checks. The spawn capsule’s 35 cm radius and 90 cm half-height are prototype geometry. They are separate from the body radius used for avoidance later in the article.
UE collision alone leaves a gap: the current skeletal proxies have no blocking collision. A logical pedestrian can occupy a point while the capsule query still reports space. An additional check therefore examines formal population members across sources using runtime positions. It supplies body occupancy absent from the proxy. It is not a complete world pedestrian grid and does not establish coverage of all unregistered objects.
Supplementary video: Spawning at an occupied pedestrian position, approximately 6.67 seconds. An existing logical pedestrian blocks admission; vacating the position permits a later attempt. This checks cross-source pedestrian occupancy. The separate physical-blocker clip checks capsule collision. Neither substitutes for the other, and the supplementary footage retains its earlier recording version.
Rejection retains demand for a later cycle to reconsider. Creating a character first and hiding its model would not establish admission merely because no overlap appears on screen. Counts, entity identity, and visible results would already disagree at birth.
Connect resource preview, candidate claims, and publication
The realization entry point operates on a demand already registered to a source. If model bindings are required, it first previews selection and records the resource admission reason and available bindings. If resources are not ready, it returns before creating a pedestrian. Preview and commit are separate: establish that bindings are available, attempt placement and entity attachment, then commit the selection after the whole batch attaches. Resource readiness is not publication of world members.
The native candidate branch passes an admission callback to the claim runtime. The callback reconstructs the root position from the candidate’s route progress, then checks crossing conflicts, finite coordinates, the non-creation area, and spatial observations. Occupancy checks cover logical pedestrians already in the block, other active population sources, positions admitted earlier in this batch, and capsule overlap when a physics scene exists. A call-local list lets later candidates exclude positions already accepted in the batch, before those entities are published.
This call-local list covers the interval between accepting a candidate and publishing its entity; source and realization records remain responsible for formal membership. Cross-source checks are limited to registered population. Mission pedestrians, standalone demonstration entities, and unregistered objects are not all included in a unified spatial index. Without a physics scene, the capsule branch supplies no native collision evidence. Logical clearance does not replace that missing evidence.
The capsule’s coordinate convention matters too. A route provides a feet-root position; the overlap query offsets its center upward by the half-height and a small allowance. Treating the feet root as the capsule center would place its lower half inside the ground and test different geometry from a standing body. Spawn and walking geometry have separate configurations even though both use capsules.
After claims succeed, realization acquires entities individually. It tries the reuse pool first and creates a new entity if no compatible entry is available. A compatible entry still in quarantine instead defers this batch; this path does not create an extra pedestrian to bypass quarantine. Attachment uses the admitted route progress. With native spatial mode enabled but no registered candidate graph, the call also returns blocked instead of falling back to a legacy position allocator that lacks the current admission evidence.
Resource blocking, placement blocking, and reuse waiting have different recovery conditions. Bindings must become ready, a candidate must pass renewed checks, or quarantine and matching must become eligible. All can leave the screen without a new pedestrian. Diagnostics should retain the specific cause so the appropriate condition governs retry.
Unwind partial work when a batch fails
Realization retains the handles already attached, whether each came from reuse, and its original pool entry. These records support failure handling. If an entity cannot attach, or model-selection commit fails after attachment, earlier successful work must be addressed. A complete-batch demand cannot silently become a partially successful demand.
If the current item fails attachment, its own branch first attempts restoration to the pool or requests removal according to whether it was reused or newly created. Batch compensation then attempts to detach earlier successful attachments in reverse order. Newly created entities receive deferred world-removal requests. Reused entities go through the restore entry point and return to suppressed pooled state. Candidate claims are released on failure as well. Restoration retains the entity, its handle, and its quarantine record for later acquisition checks.
Cleanup has its own outcome. Detachment and restore or removal-request results contribute to whether compensation completed, with a distinct failure status when it did not. This is bounded compensation for the current realization procedure, rather than a general transaction over all world state. Acquisition, admitted placement, and route ownership still execute at their respective boundaries.
The following summary covers batch compensation. Before reaching it, the currently failed attachment has already attempted restoration or removal in its own branch and is not in attachedItems. Names are neutralized and result structures and diagnostics are omitted; this is an ordering summary, not a replacement for the complete function:
if attachmentFailed or resourceCommitFailed:
cleanupComplete = true
for item in reverse(attachedItems):
detached = detachFromSource(item)
released = restorePoolEntry(item) if item.wasReused else requestWorldRemoval(item)
cleanupComplete = detached and released and cleanupComplete
releaseCandidateClaims()
return cleanupComplete ? failureReason : RollbackFailed
publishCompletedDemand()
Only a fully attached batch with successful resource commit clears the demand’s Pending state, removes its pending-source index, and stores the completed realization. A temporary entity having existed during an attempt is different from a demand having been published successfully. Failed partial work may be withdrawn and must not be counted as final population growth.
How population cycles allocate processing opportunities
Placement checks establish whether a birth position is admissible; cycle scheduling determines the available processing opportunities. Targets determine shortfalls; cycles allocate processing opportunities. Pedestrians and vehicles retain separate cycle debt rather than sharing a per-frame generation counter. Their rates and outstanding work differ, and changing one configuration should not erase the other’s debt.
With debt representing accumulated opportunities, rate the cycle rate per second, and dt elapsed time, the basic relationship is:
rate = frameRate × cyclesPerFrame
acceptedDt = min(dt, maximumFrameTime)
debtNext = debt + acceptedDt × rate
A cycle is a population-processing opportunity, not a rendered frame or a guaranteed birth. The implementation retains frameRate and cyclesPerFrame separately for pedestrians and vehicles instead of collapsing their configuration provenance. Intermediate calculations use double precision, with a 1e-6 tolerance at integer boundaries. The formula explains debt accumulation; it does not replace those boundary rules.
Catch-up processing remains bounded
Vehicle debt can produce multiple cycles when compensation conditions are met. Pedestrian processing retains an alternating limit: during consecutive updates with vehicle compensation, pedestrians alternate into a single-cycle cap. Deferred debt survives. Outside that limit, maximum accepted frame time and the pedestrian cycle rate determine the cap.
This prevents every population type from catching up without bounds after a long frame. Maximum accepted frame time currently defaults to a 0.1-second engineering setting. Time beyond the cap is not fully added to this population clock; it is not a recovered universal reference-engine constant. Pausing adds no new debt and does not erase existing fractions or deferred work.
A failed generation attempt still consumes one cycle of its type, while demand remains retryable. Otherwise an occupied candidate could be attempted repeatedly in one update, bypassing the processing budget and delaying other work. Cycle consumption measures attempt cost; retained demand records an unmet requirement.
Batch creation offsets later opportunities
An existing atomic batch can create several members during one processing opportunity. The extra creation is recorded against that type, then offset by later cycles. New generation for that type is blocked until the outstanding creation charge is repaid.
Consider a teaching example with no prior creation charge. One cycle creates a batch of 4 entities: record 4, repay 1 for the current cycle, and leave 3 for later cycles. The batch does not become four separately visible births, nor does an ordinary single-person request always create four pedestrians. The atomic batch limit is project configuration, not a recovered fixed batch size.
District budgets, authored route candidates, and atomic reservations remain project policies. They preserve distinctions among budget, opportunity, and actual creation without covering complete city density, every vehicle generator, or scenario population queues.
Separate cycle planning from execution accounting
The cycle runtime first builds a processing plan in Advance; the world bridge then executes work by owner type. Configuration validates each frame rate, cycles-per-frame value, and maximum accepted time, including bounds on integer conversion. Rejected configuration is not a reason to assume an invented default rate. Configure and Reset are separate operations, so ordinary reconfiguration does not mean clearing accumulated debt.
An enabled valid update adds clamped elapsed time. Vehicle cycles are the floor of vehicle debt plus the existing tolerance; planned cycles are deducted and the fraction remains. Pedestrian limits depend on vehicle compensation this update and whether pedestrian compensation was deferred previously. Available pedestrian cycles then come from their own debt. Alternation is persistent state, rather than a flag initialized identically on every call.
The world bridge processes vehicle cycles before pedestrian cycles. Demands and retirement requests are filtered by the current owner type. A cycle can enqueue a new single-agent managed demand and remove at most one entity; ready, previously queued atomic batches follow the existing demand path. Planned opportunities, actual creations, and pending demands are therefore different counts. A single SpawnCount would lose information needed to diagnose them.
For example, an occupied candidate consumes the current opportunity while leaving its demand pending. A later opportunity checks admission again. If a pedestrian has meanwhile been claimed by a script, withdrawal can reject retirement even when the region wants fewer people. A budget difference is not removal authority. Sharing a scheduler does not let generation and retirement cancel each other’s eligibility gates.
Creation spillover is separate from time-derived debt. The latter represents accumulated processing opportunities. Spillover represents creations already performed by an earlier batch that later cycles must offset. New generation is blocked while this offset remains, but cycles can continue paying it down. Combining these records would lose owner-type information and obscure pause, failed attempts, and successful batches.
Several implementation gaps remain. Cross-type accounting for a vehicle creating its driver is not completed here. Regional density and authored candidates remain prototype policies. This section describes the implemented independent clocks and their consumers, rather than a complete citywide generation ledger for every pedestrian and vehicle source.
Retirement first checks whether another system still needs the pedestrian
Moving the observer away does not authorize population to withdraw every pedestrian immediately. Someone handling an event, executing a scripted task, or preparing to enter a vehicle may still be referenced elsewhere. Spatial conditions answer whether distance and visibility allow removal. Relationship checks answer whether population may withdraw this particular entity.
The read-only eligibility check first rejects Mission and already-pooled pedestrians, then checks occupancy, vehicle intent, and entry/exit interactions. Unfinished Pending or Active tasks outside population-owned defaults prevent withdrawal. Current events and active candidates awaiting the next full intelligence update also protect the entity. Population can use its reset process when only its own default tasks remain.
The reference mechanism and engineering adaptation differ here. Nondefault active tasks and current events blocking reuse have source support. Protecting Pending tasks and unconsumed event candidates is a conservative adaptation between UE update phases. Reusing this local check for retirement prevents population reduction from bypassing relationships; it does not imply that original deletion and reuse used one identical predicate.
Retirement estimates and actual commits share the check. Otherwise budget planning could count an entity as removable while the eventual commit clears a newly installed task. Checks retain specific rejection reasons. Callers cannot interpret every rejection as “too close” or clear events and seats merely because population demand changed.
Horizontal distance and frustum jointly determine spatial removal
After eligibility passes, spatial policy separates nearby retention, intermediate offscreen removal, and removal beyond a farther threshold. Let d be horizontal distance, Rout the offscreen threshold, and Rin the farther threshold:
d <= Rout: retain
Rout < d <= Rin: remove only if offscreen and aggressive cleanup is allowed
d > Rin: spatial removal is allowed without requiring offscreen status
Rout and Rin include current multipliers and express spatial conditions only. Ownership, tasks, events, vehicle relationships, and non-removal areas can still reject withdrawal. At d=Rout, retain the pedestrian. At d=Rin, intermediate-band offscreen rules still apply. Horizontal distance also prevents elevation alone from causing premature retirement based on three-dimensional slant distance.
Multiple local views protect conservatively: any valid view requiring retention prevents removal merely because another observer is distant. Missing or invalid observations do not authorize automatic deletion. Explicit world, source, or scene destruction has separate lifetime authority, outside the full control of ordinary population policy.
Per-pedestrian multipliers change removal distance only
A per-pedestrian multiplier scales removal distances, not spawning distances, and does not bypass task or ownership checks. Model defaults and runtime overrides remain separate. Reset reads the currently bound model default rather than always assigning 1. New or reused ambient pedestrians reapply that default, preventing a previous lifetime’s temporary override from carrying into readmission.
Control consumes per-frame protection
A world-wide request to suppress aggressive ambient cleanup is consumed by the next Control update. All population cycles in that update read the same snapshot; repeated requests only keep it true. Without reassertion, ordinary rules return on the following update. No successful spawn, no street section, or suspended population processing must not extend a consumed request. If the world has not advanced, the consumption boundary has not been reached and the request remains pending.
Under the corresponding configuration, the request increases removal-distance thresholds, widening the retention range, and disables intermediate offscreen aggressive cleanup. Entities beyond the expanded farther threshold may still pass removal checks. The default special multiplier is 1.6; this is not permanent immunity. The per-pedestrian range multiplier applies last and cannot replace a request consumed at a world Control boundary.
Task flags reset at task-update boundaries
Ordinary extra-distance and task extra-distance flags have different reset points. The former resets during pedestrian Control; the latter resets only before a full task update. Partial or suppressed task updates preserve the task flag. An active primary task can reassert it during full processing. Replacing both rules with a timed expiration would change phase semantics.
Law-enforcement classification currently projects resource information into a Boolean. A flagged pedestrian in that class selects the cops scale; other qualifying branches select the special scale. The per-pedestrian multiplier applies afterward. Cops and special scales do not multiply together. Complete pedestrian types and task trees remain unintegrated; these flags do not establish that all associated pursuit or medical tasks ran in this article’s tests.
Why eligibility queries remain read-only
Withdrawal eligibility reads the pedestrian, intelligence state, and relationships, then returns a blocking reason. It does not remove the condition on the caller’s behalf. Canceling a task or clearing an event during a budget query would let the estimate itself change the scene. Actual retirement would then read state already changed by an earlier query. Repeated queries would have different side effects.
The current task check reads both the active flag and Pending or Active lifecycle values. Checking only whether execution has begun leaves a phase gap: a submitted task can await the next full intelligence update while population retires its entity. Active event candidates receive similar protection. The interval between queueing a candidate and selecting the current event is not an interval without a consumer.
Population default tasks are recognized through a dedicated ownership predicate. A task named Walk is not automatically disposable; a script may request walking along the same route. Only work within population’s permitted default-task ownership can be cleared by its reset procedure.
The reason also identifies the recovery owner. Protected tasks await completion or cancellation; events await intelligence processing; vehicle relationships await their relationship APIs. Population cannot declare those operations complete to meet a lower target. Using the same read-only rule at actual submission keeps the criterion consistent. The query provides no lock; submission must recheck eligibility rather than cache an earlier result as lasting permission.
How script claims change ownership and population counts
A script retains a pedestrian by registering ownership explicitly. The exposed subset contains Ambient and Mission. Claiming an ambient pedestrian changes it to Mission and records the caller’s owner identity; release restores Ambient.
Video 2: Script ownership, 7.4 seconds. A is claimed while B remains ambient. At a distance, B retires and A remains. Releasing A restores ordinary removal. This demonstrates ownership protection, not a newly executed scripted action.
Claims retain the original handle and current tasks rather than deleting and recreating an entity to simulate conversion. Repeating a claim by the same owner is idempotent. Taking another script’s entity requires explicit transfer permission. Only the current owner can release it; possessing a handle is not permission to end someone else’s protection.
| Operation | Identity and type | Count change | Tasks and relationships |
|---|---|---|---|
| Claim ambient pedestrian | Original handle retained; Ambient becomes Mission | Removed from ambient counts; physical source capacity remains occupied | Current tasks and relationships retained |
| Repeat claim by same owner | Identity and ownership unchanged | No repeated count change | No repeated initialization |
| Request by foreign owner | Rejected without authorized transfer | Unchanged | Rejection does not clear old state |
| Release by current owner | Mission becomes Ambient | Later reconciliation uses current type | Current implementation keeps tasks |
| Population retirement after release | Ordinary eligibility and spatial checks run again | Membership decreases after retirement commits | Release does not clear other protection |
Mission pedestrians do not undergo ordinary ambient retirement or reuse. Population-default behavior must not install, suspend, or complete ordinary tasks for them. The same entity continues to occupy actual source capacity after leaving the ambient count. Replacement births remain subject to that capacity.
Release removes this script ownership only. Tasks, events, seats, and vehicle intent remain in the current implementation. If they still protect the pedestrian, ordinary retirement waits. Full original cleanup also changes gameplay properties and replaces tasks; those unported operations are not implied by a successful Release return value.
The caller currently supplies a unique owner identity per session. There is no full script VM attaching an implicit current handler, complete cleanup when a script exits, network ownership migration, or streaming-reference pinning. Callers retain their identities and release explicitly when finished.
Why the same pedestrian appears in different counts
A claim changes business ownership without removing the entity connection between its source and the world. Reconciliation counts ambient members by current population type, while actual source capacity still counts attached entities. Ambient count measures the shortfall in ordinary population; actual capacity measures how many objects the source already hosts. Removing a mission pedestrian from both counts would invent a free capacity slot on every claim and let repeated claims exceed the source limit.
This also explains why claiming pooled pedestrians is rejected. A pooled entry retains a valid handle but has left active population with updates and tasks suppressed. Allowing a script claim merely because the world can resolve that handle would let script ownership and pool management claim conflicting lifecycle authority. The API rejects that case before mutation.
Same-owner claims avoid reinitialization so repeated confirmation remains predictable. A script checking its ownership each update must not repeatedly change population type or reconstruct tasks. Foreign transfer requires explicit permission, and a rejected claim preserves the former owner. Release also checks the current owner; a former applicant that no longer owns the entity cannot release it.
Session tags remain caller-managed. Reusing one FName for an unrelated later script does not automatically create a new ownership generation. Unique session identity is a caller contract here, rather than an implemented global request-version service. Full script integration still needs termination handling, copied handles, and delayed requests. A successful local claim does not establish those capabilities.
Non-creation and non-removal areas are independent
A script may need one corner to remain empty while retaining existing pedestrians elsewhere. These requests act in different time directions: one restricts future births, the other protects current members. One generic “population-disabled area” could delete existing characters unexpectedly or continue filling a location intended to remain empty.
The world retains one non-creation box and one non-removal box. Each type has a single slot: setting it replaces the previous box of that type, and each clears independently. These are not arbitrary collections of volumes and do not merge automatically.
Containment uses the XYZ coordinates of the pedestrian root or actual spawn candidate, including boundaries:
inside = minX <= x <= maxX
&& minY <= y <= maxY
&& minZ <= z <= maxZ
These chained inequalities are mathematical notation, not directly usable C++. Unlike horizontal range checks, boxes include height. A footprint alone cannot establish whether an elevated or underground pedestrian belongs to the same box.
Video 3: Creation and protection areas, approximately 11.93 seconds. With both pedestrians present, A’s area blocks creation and B’s blocks removal. Setting A’s box does not delete its existing pedestrian; B remains at a distance. On return, clearing only A restores its replenishment. Clearing B and moving away restores ordinary removal on both sides.
Non-creation is checked before entity creation and blocks future ambient births only. Existing pedestrians continue. Clearing the box still leaves pending demand subject to budgets, placement, and resources. Non-removal protects existing ambient members against automatic retirement and spatial culling without revoking explicit world destruction authority.
The world owns box state. Route refresh, camera-observation updates, and scene rebinding must not clear script settings implicitly. World shutdown or reconstruction clears them. Invalid set inputs are rejected before overwriting an existing valid box. The implementation checks finite coordinates and ordered minimum/maximum values.
Hidden initialization requires observed screen state
After loading or a warp, population may need to fill nearby space quickly. Requesting initialization does not mean the player can no longer see the world. Enabling close births on an API call alone would still produce visible pop-in.
Hidden startup requires both a startup reason and an actual fade observation. Reasons can include forced initialization, continuous full fade, an existing startup flag, or an active instant-fill request. Close-range admission additionally requires the minimum fade across relevant valid local views to be strictly greater than 0.9.
hiddenStartup = hasStartupReason
&& allRequiredViewsValid
&& minimumLocalFade > 0.9
No view, missing fade data, or only partially hidden views do not establish that every relevant screen is covered. Revealing the screen immediately restores ordinary visible/offscreen rules; close-range permission does not carry over from the previous hidden period.
Video 4: Fade initialization, 11 seconds. Requests made while visible leave the nearby area empty. Actual PlayerCameraManager fade allows population to fill while hidden, then walking continues after reveal. Default ranges remain in use. Continuous full fade is itself a startup reason, so birth cannot be attributed exclusively to the second API request during the fade.
Initialization windows and instant fill use different clocks
Forced initialization defaults to 0.7 seconds, retaining millisecond boundaries internally. Reaching the end time differs from passing it; only the latter expires the window. Early completion with no pending population demand also requires strictly more than 100 ms. Repeated requests can extend the deadline without shortening an active window. The public interface uses seconds, while conversion and range validation remain necessary internally.
Instant fill advances by population-processing frames, defaulting to 10 updates with 2 extra Ped cycles each. Repeating an active request does not refill its counter. The count decreases once per population Control update, not per pedestrian, candidate, or catch-up iteration.
Hidden startup also permits bounded extra generation attempts. The authored-candidate adaptation currently allows up to 100 during hidden startup and 2 otherwise, stopping early when there is no generation work. Targets, placement, resources, and relationships still gate attempts; successful creation enters the offset record. Complete path-service synchronous refresh, abort, and scenario/wildlife asynchronous queues have not been ported here.
Burst processing must not advance reuse quarantine repeatedly
Quarantine advances once per eligible world Control update. Instant-fill passes and catch-up loops within that frame must not each advance it. Otherwise a configuration requiring two updates of quarantine could be satisfied by one burst, reusing an entity before its phase handoff has completed.
Recording this feature exposed a visual-proxy leak. Before formal population had spawned successfully, the demonstration’s bootstrap characters remained visible. Early telemetry inspected additional proxies only and missed those existing objects. The fix moves formal-population presentation ownership immediately after scene preparation, withdrawing old demonstration proxies before the first demand can be rejected. It does not hide admitted population to manufacture an empty scene. Final recording checks bootstrap proxies too. Failed footage remains in diagnostics and is excluded from the published clips.
Keep repeated requests from rewriting initialization state
The startup runtime retains current Control time, forced-window start and end, the consecutive-full-fade count, and remaining instant-fill updates. A forced-window request validates its input before quantizing duration to milliseconds. The first request establishes the interval; an active interval takes the later of its existing end and the requested end. A shorter repeated request cannot accidentally terminate an earlier longer window.
Time advancement and observation have different responsibilities. Time advancement checks whether the deadline has been exceeded. Observation handles early completion when no ambient demand remains and updates the full-fade streak. The streak uses a near-fully-black threshold, whereas hidden admission requires fade strictly above 0.9. These are not interchangeable flags simply because both read fade. The former contributes a startup reason; the latter permits close hidden spawning now.
Instant fill starts only when its remaining count is zero. Repeating an active request does not refill that count. Completing population processing decrements the processed-frame count regardless of successful births. Otherwise an update without valid placement could retain fast mode indefinitely, while a successful batch could exhaust the whole window at once. Request lifetime is kept separate from creation results.
Reuse quarantine does not advance inside the extra-attempt loop. Its world-owned frame advances once for the relevant update. Trying more candidates means doing more admission work, not passing through more world phases. Separate startup, catch-up, and quarantine state prevents a larger fill budget from also changing reuse timing.
To diagnose fade initialization, inspect valid observations and startup reason first, current hidden admission next, then resources, placement, and capacity. An accepted initialization request can produce no pedestrian because later gates remain closed. Its success return alone does not identify the blocking stage.
Retirement into the pool retains the original handle
Retirement withdraws population membership before the reuse manager takes over. Pool entry disables the relevant updates, clears the currently covered population-default tasks and pooling state, retains restoration data, and starts quarantine. Route executors and spatial projections still own their state separately; this entry point does not clear it all. Logical entities and handles remain until actual eviction or destruction ends their identity.
This requires different checks from deleting an Actor offscreen and later spawning another with the same model. Pool entry needs membership withdrawal, disabled updates, task reset, and source checks. Reuse needs matching, quarantine, new placement, restored tasks, and movement. A queryable original handle is normal for this implementation, not a reason to declare retirement unsuccessful.
Video 5: Retirement and reuse, 9 seconds. Pool count goes 0→2→0, original handles are readmitted, and both pedestrians resume updates and walk independently. This clip was recorded after the final readmission fix. Its black interval comes from actual fade. Counts and visible movement are checked together; pool count alone does not establish success.
Reject pool admission before affecting unrelated entries
A full bounded pool may need to evict an older entry. First, however, it checks request identity, type, duplicate entry, and protected relationships. Evicting for capacity before discovering that a candidate is script-protected would reject the request after destroying an unrelated valid pooled entity.
The current flow performs read-only checks before capacity handling and reset. Pedestrians use withdrawal eligibility. Vehicles also check driver, command owner, occupants, and reservations so passenger occupancy cannot be lost merely because no driver exists. These are relationship invariants, not acceptance of a complete vehicle-reuse mechanism.
Acquisition also checks source matching and quarantine
Entries retain type, model binding, retired source, source generation, and retirement Control frame. Acquisition matches the world, type, and required binding. Same-source reuse requires a later source generation. Cross-source reuse requires the corresponding observer-safety conditions. Quarantine must then be satisfied.
The current two-Control-update quarantine and source epoch are project policies, not original constants or a universal incarnation system. Epoch distinguishes uses of a population source. It does not mean networking, scripting, rendering, and every other consumer share one invalidation token.
Successful acquisition clears the pool flag and task suppression and requests restoration of update phases. Population realization still has to attach the new position and source. Acquire success is not atomic restoration of every downstream state. Attachment and plan initialization return their own results, whose failure paths still require handling.
A pool entry describes a particular retirement
The pool stores more than available handles. An entry retains entity type, archetype binding, retired source and generation, retirement frame, admission serial, reset version, original update flags, and observer-safety state at retirement. Matching consumes several of these fields; restoration uses the update flags. Serial and version retain admission and reset information. A source generation is not the entity handle’s identity.
Same-source acquisition requires a newer source generation than the retired one. Calling Acquire again does not satisfy it automatically. Cross-source acquisition instead requires observer safety at both retirement and the destination source. World, agent type, archetype, and quarantine checks still apply. A compatible but quarantined entry is distinguished from having no compatible entry at all.
A Boolean summary makes the source condition explicit. World, type, binding, and request validation still surround it. Generation here belongs to the source, not the entity-handle value:
sameSourceEligible = sameSource && retiredGeneration < currentGeneration
crossSourceEligible = !sameSource && safeAtRetirement && safeAtDestination
sourceEligible = sameSourceEligible || crossSourceEligible
quarantineReady = currentControlFrame − retiredControlFrame >= requiredFrames
Successful acquisition removes the pool record, clears pool membership and task suppression, and requests restoration of the saved update phases. Outer realization then attaches the admitted position. Acquired completes the pool side of recovery. Outer attachment still establishes the new source and route relationships.
Admission is layered too. It removes invalid cache records, rejects duplicates, wrong entity kinds, and protected relationships before capacity eviction and reset. Rejection preserving unrelated entries refers to valid cache entries and candidate state; it does not mean the function never tidies invalid records. Later eviction and reset are not presented as an infallible transaction across the world.
If realization subsequently fails, Restore uses the saved entry and applies pooled-state reset again. An already mature quarantine is not automatically treated as a first retirement through this interface. Restore can itself fail, so outer compensation must inspect its result rather than assuming that re-adding an array entry proves a complete rollback.
Reuse stall: the old route interferes with readmission
Symptom and diagnosis: acquisition succeeds but movement does not resume
The final failure in this work appeared after acquisition. Pedestrians had left the pool, retained their handles, and restored active counts, but positions did not advance as expected. Checking only entity identity and a reduced pool count could mark the run successful.
Two adjacent stages caused the problem. Old route/spatial projections retained position-write authority, suppressing attachment at the new candidate. Even after attachment could proceed, closed planner history could still seed the next route from an old origin rather than the newly admitted position.
Attachment fix: revoke old position authority after successful acquisition
While a formal route is active, preventing other modules from rewriting its pedestrian’s position is justified. Once the entity leaves that population, enters the pool, and is acquired again, old authority must no longer block a new spawn location.
The fix runs after successful acquisition and before new attachment. Reused entities relinquish old route and spatial projection authority, then attach at the route progress already approved by admission. Active pedestrians are not all cleared unconditionally, so normal live-route transfers retain their rules.
The following neutralized call-order summary omits entity creation and error branches:
Successfully acquire an eligible reuse entry
If this is reuse: relinquish old route/spatial position-write authority
Apply the current model-default removal parameters
Attach the pedestrian at the approved candidate's route progress
Let the new route own subsequent movement from current state
Planner fix: history needs a valid basis for continuation
The planner retains its latest plan for diagnostics. Deleting all history would discard useful information, but having a recent record does not establish that this request should continue from it.
The fix excludes old history from origin inference only when all relevant conditions hold: no active plan, no explicit source endpoint, and no completed route owned by the current population source. That request is a fresh implicit admission and initializes from the newly approved actual position.
Explicit continuations, live-route transfers, and completed routes owned by the source retain their existing paths. Erasing every route record to fix reuse would also break valid continuous walking. The fix retains diagnostic history and restricts when it can influence a new plan. Position authority is relinquished separately before attachment.
Acceptance: retain identity and measure subsequent movement
The final reuse video retains handles 78 and 79. After readmission, actual movement is approximately 308.711 cm and 572.000 cm, with minimum separation approximately 537.000 cm. These values describe that recorded trajectory, not general speed or spacing parameters.
Regression tests also add smaller counterexamples. Closed diagnostic history must not reset approved route progress during readmission. A reused entity that retained old position authority must still attach at the new candidate. These cases test the causes directly; the formal video then checks that both pedestrians actually walk. Each form of evidence serves a different purpose.
Fix the consumers of stale state
The failure has distinct dependencies. The pool establishes that the same entity is reusable. Attachment needs authority to place it at the newly admitted candidate. Planning needs a valid basis for constructing its future route. New entities often satisfy all of these together because they have no history. Reused entities require each handover explicitly.
Restoring more pool flags alone would not remove old route authority at attachment. Forcing a position once would not prevent the next planning request from selecting a historical origin. Deleting all history would break legitimate transfers and explicit continuation. The fix therefore revokes old position authority before attachment and limits historical inference at the planning entry point, where stale state is actually consumed.
Source ownership matters in planning. A recently completed record proves past completion, not that the current population source owns that completed route. The latter is needed by the relevant continuation branch. An explicit source endpoint is also a caller-supplied continuity requirement, unlike an origin inferred from diagnostic history. With no active plan, explicit endpoint, or current-source completion basis, the admitted physical position supplies the new-plan basis.
Tests follow these dependencies. One leaves old position authority on the reused object and checks actual placement at the candidate. Another retains closed history and checks that new planning respects the approved position. The final clip then checks continuing movement by both pedestrians. These cases do not prove every possible route-history combination, but they prevent fixing one visible symptom while another consumer overwrites the state on the next update.
Animation reads movement rather than driving population
If a logical pedestrian has stopped while its walk clip continues, or the model snaps orientation on reversal, correct task results become hard to observe. Presentation needs improvement without Root Motion replacing the route’s displacement authority.
Visual proxies follow logical entities, and animation Root Motion does not drive logical movement. Gait playback uses measured speed, with walk-clip advancement stopped at rest. Near-view idle combines 92% reference pose and 8% existing idle. Existing two-bone leg and arm IK adjusts flat-ground posture, with wrist orientation following the solved forearm rather than stretching bones.
Video 6: Start, stop, and return, 11.8 seconds. Actual walk requests drive departure, arrival, and reversal. Presentation follows measured speed and settles after stopping. This dedicated walk host checks close-view presentation, not every formal population host or distant animation path.
Start and stop use different blend times: currently 0.16 and 0.22 seconds. The speed-measurement window is 0.1 seconds and hold is 0.08 seconds. Existing fixed-step display interpolation connects neighboring logical states. Task orientation can still change in one logical step; rendered orientation interpolates continuously without creating a separate turn task.
These are procedural adaptations over existing resources. No new start, stop, or 180° turn clips were added. Motion Matching, complete reference animation-network equivalence, and terrain IK are absent. Clearer near-view motion does not establish distant low-frequency animation or complex-ground behavior; those need separate checks.
Add presentation interpolation after logical motion
Presentation reads logical transforms and measured speed before choosing pose and gait. The speed window smooths observation; a short hold reduces repeated switching near rest. Asymmetric start and stop blends handle entry into and exit from walking separately. These are different filtering stages, not durations to add into one fixed pedestrian response delay.
Fixed-step presentation interpolation smooths visible transforms between samples. Logic advances in its own phases; rendering interpolates retained samples. Feeding the interpolated position back into the entity would let render frequency change route progress and collision input. Rotation follows the same boundary: the current task can change logical heading in one step while presentation smooths it. That is not a completed turn task or authored turning animation.
Near-camera posture correction operates on the skeleton. Reference-pose blending and existing two-bone IK adjust limbs; wrist orientation follows the solved forearm rather than stretching bones to hide errors. These operations change neither population type nor relationships nor actual displacement. Walking-clip advancement stops at rest, so continued animation playback does not falsely suggest ongoing movement.
Acceptance therefore inspects logical displacement, presentation position, and skeletal motion separately. A normal walk clip with unchanged logical position does not prove movement. Normal logical motion with visual jitter instead directs investigation toward proxy synchronization and interpolation, rather than route cost. The near-camera clip and dedicated walk host check presentation. Formal-population route and lifecycle behavior have separate tests.
Routes commit movement; avoidance only suggests steering
After spawning and retirement work, active pedestrians must still complete their routes. Following, opposing passage, static-blocker waits, and crossing conflicts occur during execution. Local avoidance suggests direction. The original task and route retain destination, progress, and completion.
The native formal-population Sidewalk branch reuses steering and body-clearance helpers from the walking module. It reads actual entity positions, headings, and observed speeds instead of establishing another independently advanced walking identity. Existing queue and physical crossing holds take precedence. Crossing, block transfer, and staged entry retain their own authority rather than being overwritten by one universal sidestepping routine.
Route progress consumes the longitudinal projection of actual displacement
Let a straight connection run from S to G, with horizontal length L, unit direction a, and connection cost C. For actual candidate position Pnext, longitudinal distance is:
alongNext = dot(Pnext − S, a)
projectedCost = alongNext / L × C
acceptedCost = clamp(projectedCost − currentProgress, 0, stepBudget)
This describes the current straight-sidewalk adaptation. Total detour distance cannot be added directly to route progress. Repeated obstacle probing must not logically finish the route early. A candidate that fails ground, collision, or body-clearance checks commits neither a new physical step nor artificial progress.
Completion also requires proximity to the actual goal. A pedestrian offset sideways cannot finish merely by crossing the goal’s longitudinal plane while remaining distant. The adaptation constrains reverse projection and out-of-bounds candidates to preserve monotonic advancement along the original connection.
Convert movement budget in the formal Sidewalk branch
Route cost need not equal world length. Let the connection cost be C, its horizontal endpoint distance L, and this step’s route budget B. The local executor converts cost budget to a proposed physical distance. After physical acceptance, it converts actual longitudinal progress back into the same cost units. Here S retains its earlier definition: the start of the current connection, not the pedestrian’s position at the beginning of this step. previousProgress is the connection progress accumulated before this step. This expression describes the current straight Sidewalk adapter, not every connection type:
requestedStep = max(B, 0) × L / C
alongNew = dot(Paccepted − S, routeAxis)
acceptedCost = clamp(alongNew / L × C − previousProgress, 0, B)
This preserves planner cost representation while collision works in centimetres. Near-zero cost or length excludes this conversion path; collision queries must not be left to handle division errors. Lateral displacement also cannot turn total diagonal travel into longitudinal route cost.
Same-direction following first reduces available physical distance. The implementation separates another pedestrian into Ahead and Side components relative to the route. Within the body’s lateral width, circular geometry supplies a longitudinal clearance requirement. An additional step-distance margin accounts for later commits by other sources in the current execution order. It is not a universal human following distance. If no forward space remains, the local result retains the position and sets route budget to zero.
Local steering is activated afterward for opposing bodies, predicted conflicts at other headings, lateral offset, or physical blockage ahead. A queue or crossing hold already constraining movement cannot be bypassed sideways by the helper. Conflict-free aligned walking can retain the existing route path; the system does not unconditionally rebuild navigation for every pedestrian at every step.
Endpoint acceptance checks actual arrival too. A candidate cannot move backward along the connection or exceed its end. Near the longitudinal end, excessive lateral distance from the goal also rejects the step. Otherwise passing beside an endpoint could count as arrival merely by crossing its plane, producing a jump when the next connection takes over.
Body prediction detects crossing conflicts
Checking only directly opposing pedestrians misses diagonal and perpendicular approaches. The shared helper represents pedestrians as horizontal body discs and checks their relative motion within a candidate horizon. Let Ps be the current self position, E the candidate endpoint, Po the neighbor position, vo its observed velocity, and h the horizon:
r0 = Ps − Po
r1 = E − Po − vo × h
closest = the three-dimensional closest point from the origin to segment [r0, r1]
clear = lengthXY(closest)² >= (2 × bodyRadius + padding)²
The code order matters: compute the three-dimensional closest point, then compare horizontal length. Replacing it with a purely two-dimensional closest-time formula would not establish identical execution. Retired entities are ignored and height differences are filtered. Stationary or arrived neighbors still occupy space; zero velocity does not remove them.
The horizon generally comes from lookahead distance divided by desired speed; neighbor velocity comes from an observation window. Current project settings use a 30 cm body radius and 3 cm padding, giving a 63 cm safety-diameter term. Lookahead is 100 cm, opposing scan range 250 cm, and velocity window 0.2 seconds. These are separate from spawn capsules, visual scale, and animation rate.
Video 7: Three-way passage, approximately 4.67 seconds. Formal population approaches from different directions, avoids locally, continues along original routes, and stops at original goals. No script manually queues, relocates, or retargets pedestrians. This checks the small scene, not crowded-city behavior or global junction-priority scheduling.
Steering selection and physical checks remain separate
The current candidate fan tests 0°, ±25°, ±50°, ±75°, ±90° around the desired direction. Candidates pass ground projection, traversability, and predicted body clearance before comparison by dot product with the desired direction. Positive-angle candidates receive a 0.03 preference to reduce perfectly symmetric opposing choices.
This is a UE adaptation, not complete recovery of tangent candidates and scoring. Ground checks also depend on scene tags and physical evidence, with bounded height differences and sample spacing. Actual short steps are checked again after candidate capsule sweeps. A promising direction does not authorize the next displacement automatically.
Pass steering candidates through scene checks
Scoring favors alignment with the desired heading and uses a small fixed-side preference to break symmetric choices. That preference applies only after safety checks; it cannot make a wall-crossing candidate admissible. It is neither junction right-of-way nor pedestrian priority.
Each direction is projected onto a walkable surface and checked for traversal and relative-body clearance. The formal Sidewalk adapter requires a ground trace to hit an object carrying the designated walking-surface tag, with a sufficiently upward normal. Intermediate ground samples reject gaps that valid endpoints alone would miss. Capsule sweeps test body-volume clearance. UE scene callbacks supply these conditions; the helper does not own map semantics.
When static geometry blocks direct travel, the adapter also checks whether a side step has a forward exit. A clear lateral step beside an unbroken wall is not an exit. Without this check, opposing lateral candidates can alternately score well and produce repeated sideways probes without progress. Exit probes participate in candidate evaluation, while the actual short movement step is checked independently.
After selection, execution constructs a shorter endpoint within the current budget and repeats ground, capsule, and body-clearance checks. The prediction window and the actual submitted step have different purposes. Any rejected step retains position and consumes no route progress; a later update can evaluate changed obstacle and body positions.
This remains a bounded local adapter. It does not implement complete tangent scoring, global crowd costs, or crowd-deadlock resolution. A fixed-side preference cannot guarantee convergence at arbitrary density or update order. The three-person crossing clip demonstrates its particular small scene, rather than citywide pedestrian capacity.
Keep the original plan when no local exit exists
An early full-width wall case still allowed safe lateral steps, causing pedestrians to probe sideways without finding an exit along their route. Positions changed, but useful advancement did not. Static-blocker candidate checks now add a forward local-exit probe along the original route direction. If no candidate passes, the pedestrian waits instead of treating lateral motion as progress.
Supplementary video: Blocked wait and resume, 7.6 seconds. A real full-width obstacle stops the pedestrian; removing it resumes the original plan. The case neither replaces the entity nor requests route replanning. It checks bounded local handling, not global detours around arbitrary concave obstacles. This supplementary clip retains its earlier recording version.
This formal-route wait/resume path differs from replanning that can occur in the dedicated walk host. They share local helpers; consumers still own task lifecycles and failure policy. One host’s Replan behavior does not define recovery for all population routes.
Other clips cover narrow passages, queue recovery, and obstacles enabled or removed at runtime. The runtime-blocker case changes static collision geometry; it does not test prediction of fast vehicles. The passage case has no general corridor reservations or global deadlock solver. Waiting when no local candidate is safe is an intentional result.
Reject stale paths in the dedicated walking host
Formal population routes and the dedicated walk host share geometry helpers, not one task executor. Dedicated walking state retains its goal, path points, current corner, request generation, waiting status, and blockage times. A new goal increments generation, withdraws the old path, and resets the motion and progress state needed for the new request. Cancellation also increments generation, preventing an outstanding old query from reactivating it.
Path acceptance checks the agent index, request generation, and whether a query remains pending. A late result cannot replace a newer goal simply because its geometry is valid. After identity checks, failure information, an empty path, or an endpoint outside the goal tolerance can still reject it. Walking starts only after those checks pass. This protects the dedicated host’s asynchronous boundary; it does not imply that every formal-population plan API uses the same reply structure.
Comparing the reply with the generation retained by its request separates stale results from failure of the current query. This entry-point summary omits index validation and result structures:
if reply.generation != state.generation or !state.pathPending:
rejectStaleReply()
else:
state.pathPending = false
if queryFailed or pathEmpty or endpointOutsideGoalTolerance:
state.status = Failed
else:
installPath()
state.status = Walking
Rejecting an old query must not mark a newer query failed. Only the matching current query can update its pending state. Otherwise a late old failure could cancel a new task whose goal has already changed.
The dedicated host also separates inexpensive movement updates from more costly steering evaluation. Control changes steering cadence with near/far state and requests renewed evaluation when returning from far to near or when a timed standstill expires. Actual movement continues checking ground and bodies. It divides elapsed movement time into bounded substeps rather than discarding the remainder after a hitch. That differs from the population-generation clock’s maximum accepted elapsed time; the two bounds are not interchangeable.
Advancing a corner must not allow an unfiltered first step toward the raw goal. The new direction passes through the same helper, preventing repeated retries from creeping toward a wall. The host separately accumulates blocked time and lack-of-progress time before bounded replanning. This recovery belongs to the dedicated walking entry point. Formal population queue holds and crossing constraints retain their own route rules.
Choose observations by the failing stage
A stationary pedestrian can have several causes. Before demand exists, inspect source targets and counts. Pending demand without realization calls for resource, candidate, claim, and quarantine reasons. An attached entity without movement calls for task eligibility, active-plan state, position authority, and step rejection. Only when logical position moves but the model does not should diagnosis proceed through presentation synchronization, measured speed, and animation playback. Diagnostics should retain these stage distinctions to identify the actual blocker.
Reuse acceptance particularly needs an identity chain: retired source and generation, pool entry, acquisition result, new admitted progress, then subsequent physical positions. Population can reach its target through newly created entities. An old handle can also reappear while remaining stationary. Counts, handles, and displacement answer different questions, rather than contributing to one aggregate success score.
Parameters also need their consumers attached. These values belong to the delivery branch examined here. Lengths use centimetres, times use seconds, and the normal component is dimensionless. They are not global reference-mechanism constants or tuning changes made during article preparation:
| Current parameter or check | Value | Consumer and meaning |
|---|---|---|
| Path endpoint tolerance | Absolute difference at most 15 cm per coordinate component | Dedicated host accepts a path using FVector::Equals, a component-wise comparison |
| Final arrival distance | Three-dimensional distance at most 15 cm | Dedicated host checks goal distance after path exhaustion; distinct from the component-wise tolerance above |
| Corner advance distance | Strictly below 5 cm | Dedicated host advances the corner, then filters the first step again |
| Movement substep | At most 0.05 s | Dedicated host subdivides elapsed time without discarding its remainder |
| Continuous blockage trigger | Strictly above 1.5 s | Dedicated host requests replanning |
| No-progress trigger | Strictly above 2 s | Dedicated host accumulates lack of improvement toward its corner |
| Replan count | Failure after exceeding 3 | Bounded recovery in the dedicated host, not a universal formal-population retry limit |
| Ground-normal Z | At least 0.8 | Formal Sidewalk projection eligibility, still requiring the surface tag |
| Along-step ground sampling | At most about 25 cm | Formal Sidewalk traversal, alongside height and capsule checks |
This table is not permission to add arbitrary timeouts to formal population. Crossing waits can remain valid under signal or occupancy rules and must not lose their route through the dedicated host’s blockage timeout. Reuse quarantine uses Control frames, not the seconds listed here. Each parameter needs its owning state machine and update phase as well as a value and unit.
Existing regressions and clips cover these local contracts. This article preparation did not rerun the complete engineering suite or add multiplayer or performance acceptance. The expanded explanations come from checked source and handoff records; historical supplementary clips do not become evidence from one final build. Further checks can follow each section’s inputs, state writers, rejection reasons, and outputs, then compare them with the corresponding footage.
What the tests check
The final functional record reports a successful build and 142 unique automated regressions: 57 succeeded, 85 succeeded with warnings, 0 failed, and 0 were not run. Existing world-cleanup warnings remain in the report. These 142 entries are automated tests, not rendered scenes or a percentage of reference-system compatibility.
Main clips are actual UE footage from the original city, with per-clip operations, samples, and verification. Clip 5 was recorded after the final readmission fix. Other main clips mostly use the preceding animation revision, with their exercised behavior unchanged. Clip 6 reuses accepted close-view source footage. They are not one continuous test against a single final DLL.
| Evidence | What it checks | What it cannot replace |
|---|---|---|
| Reference reading and interface contracts | Responsibilities, phases, parameter sources, and declared deviations | Actual execution of a UE branch |
| Current source | Call order, writes, and failure paths | Correct character appearance in footage |
| Automated regressions | Boundaries, protection, counts, reuse, and plan counterexamples | Every real physical scene |
| Corresponding runtime samples | Handles, positions, plans, members, and pool state | Every visible detail throughout a video |
| Actual videos and sampled frames | Continuous visible behavior, fades, transitions, and avoidance | Unshown branches, multiplayer, or performance |
Article preparation reads the handoff, mechanism notes, relevant source, and existing verification; it checks video hashes and sampled sequences. It does not rerun builds or UE regressions. Images come from actual encoded frames and are exported as opaque RGB. Mechanism diagrams are labeled separately so teaching geometry is not mistaken for measurement.
How main and supplementary clips relate to the text
Main clips follow delivery order near their explanations: spawning, protection, and reuse first, then presentation and formal-route avoidance. The supplementary index retains all material for targeted inspection. Each clip does not count as another independent experiment.
| Main clip | Duration | Focus | Principal limit |
|---|---|---|---|
| Population changes | 9.4 seconds | Spatial retirement, replenishment, and continued walking | Close-view range override; district stays loaded |
| Script ownership | 7.4 seconds | Claim protection and normal retirement after release | No new scripted action |
| Creation and protection areas | Approximately 11.93 seconds | Independent setting and clearing | One world box per type, not arbitrary volumes |
| Fade initialization | 11 seconds | Actual fade and close hidden admission | Default ranges; no exclusive attribution to the second request |
| Retirement and reuse | 9 seconds | Original handles, pool counts, and actual post-readmission movement | Local policy, not complete streaming or networking |
| Start, stop, and return | 11.8 seconds | Measured-speed animation and rendered turning | Dedicated walk host; close-view presentation |
| Three-way passage | Approximately 4.67 seconds | Body clearance and completion of original goals | Small scene; no crowd-performance acceptance |
Supplementary clips retain their earlier recording versions and were not all recaptured with the final animation. Opposing-walk and formal-population opposing-route cases use different hosts. Physical-blocker and logical-pedestrian spawn occupancy also check different objects. Their individual descriptions define their scope.
| Supplementary clip | Duration | Purpose and boundary |
|---|---|---|
| Same-route following spacing | 11.03 seconds | Spacing and admitted progress; separate earlier recording |
| Blocked spawning | 10.03 seconds | Real physical blocker; separate from logical pedestrian occupancy |
| Opposing pedestrians | 7.53 seconds | Dedicated walk host; not formal-population integration acceptance |
| Formal population route avoidance | 5.67 seconds | Demand, formal members, and opposing-route avoidance |
| Static obstacle detour | 6.20 seconds | Bounded local detour, not global pathfinding |
| Blocked wait and resume | 7.60 seconds | Full-width stop; original plan resumes after obstacle removal |
| Queue recovery | 10.00 seconds | Blocked leaders affect followers; movement resumes after release |
| Runtime obstacle enable and removal | 8.47 seconds | Static collision toggled at runtime, not fast-vehicle prediction |
| Crossing paths | 4.47 seconds | Non-opposing body conflicts; original goals retained |
| Narrow-passage waiting | 9.73 seconds | No general corridor reservations or global deadlock release |
| Spawning at a pedestrian-occupied point | 6.67 seconds | Cross-source occupancy even without blocking proxy collision |
| Per-pedestrian removal ranges | 7.40 seconds | Runtime multiplier and model-default reset; task protection remains |
| Per-frame cleanup protection | 10.73 seconds | Reassertion and return to defaults, not permanent immunity |
Continuing from a local lifecycle into the city
The work connects a repeatable street-level process. Demand passes admission to create members; formal routes advance them; scripts claim and release ownership; population retires eligible entities; and reused entities pass new admission before walking again. The reuse stall also shows why membership reappearing is not the end of validation: positions and routes must resume too.
These interfaces give later tasks, vehicles, and services usable character identity and lifecycle support. They do not complete city population reconstruction. City-wide density, original model streaming, scenario/interior/wildlife populations, network ownership, and complete task trees remain separate work. Active/Warm/Inactive describe district policy, not pedestrian Dummy/Real conversion. Conversion code for another entity type cannot establish pedestrian support either.
Event-to-Pending-task bridging, active-slot protection, and task suppression have code and test foundations. Main clips do not specifically demonstrate the full perception-response chain, so this article uses them only to explain withdrawal protection. Complete event response still needs producers, task bridges, and execution results checked in corresponding scenarios.
Further integration should retain these responsibilities: population requests and withdraws; tasks and routes decide behavior; physical queries constrain actual steps; animation reads results. More complete candidate services, character assets, and behaviors then require fresh checks at those interfaces.
AI collaboration retrospective
AI helped connect mechanism reading, population interfaces, route execution, and recordings into one account, checking spawn positions, script ownership, reuse conditions, and animation inputs. The most useful development checks retained failures such as “pool counts recover but nobody walks” and “formal population has not spawned but old proxies remain visible” for diagnosis.
Both exposed gaps in observation. Handles and counts missed actual movement; sampling only new proxies missed existing visuals. Fixes addressed readmission position authority, planner-history consumption, and presentation-ownership handoff, followed by counterexamples and actual footage. Calling them all “reset every state” would obscure the paths each change affects.
The article treats its material the same way: historical gaps are reconciled with later records, project parameters remain separate from reference mechanisms, and supplementary and final main footage retain their version boundaries. Future revisions can return to specific interfaces and runs without losing failure causes or the evidence behind fixes.












