fix: trigger area was reporting the wrong entity#7835
fix: trigger area was reporting the wrong entity#7835alejandro-jimenez-dcl merged 3 commits intodevfrom
Conversation
…pool local to avoid usage outside of the system
|
Windows and Mac build successful in Unity Cloud! You can find a link to the downloadable artifact below. |
decentraland-bot
left a comment
There was a problem hiding this comment.
Review Summary
Verdict: Approved ✅
This PR correctly fixes a use-after-pool-release bug where pooled Trigger objects were released immediately after AppendMessage, causing later CRDT serialization to read stale/overwritten data when multiple players shared the same trigger area in the same frame.
What changed
-
Deferred pool release —
PropagateResultComponentnow enqueues used(PBTriggerAreaResult, Trigger)pairs into aQueueinstead of releasing them immediately. The queue is drained at the end ofUpdate(), after all queries have completed and CRDT messages have been serialized. -
System-owned pools — The
triggerAreaResultPoolandtriggerAreaResultTriggerPoolare now created internally viaComponentPool.WithDefaultCtor<T>()instead of being injected. This simplifies the dependency chain (removed from plugin constructor andStaticContainerwiring) and ensures proper disposal inOnDispose(). -
Test cleanup — Removed the now-unnecessary pool mocks from
TriggerAreaHandlerSystemShould, keeping tests aligned with the new internal pool ownership.
Analysis
- Correctness: The fix is sound. By deferring release until after all queries complete, each
AppendMessagecallback retains a unique, stable reference to itsTriggerobject throughout the frame. - Memory: The queue is a single
Queueallocation (not per-frame), and items are dequeued/released every frame — no accumulation risk. Good. - ECS patterns: Structural changes (none here) are not affected. The pool release happens outside query iteration, which is correct.
- Disposal:
OnDispose()properly disposes both pools. ✔️ - Naming/style: Follows project conventions (PascalCase methods, camelCase fields).
CI Status
- ✅ playmode tests pass
- ❌ editmode tests timed out (80-minute CI timeout — not related to this PR)
- ❌ enforce-approvals is expected to fail until approvals are in place
Clean fix. LGTM.
Requested by Alejandro Jimenez via Slack
|
Claude finished @alejandro-jimenez-dcl's task in 3m 59s —— View job Code Review
No issues found. The fix is correct and clean. Root cause confirmed: Fix assessment: The Structural change ordering in Pool/container wiring cleanup is complete: REVIEW_RESULT: PASS ✅ |
|
Claude finished @alejandro-jimenez-dcl's task in 1m 58s —— View job Code Review
|
|
🔍 Claude reviewed this PR and found no blocking issues, but assessed it as complex — human DEV review is still required before merging. |
1 similar comment
|
🔍 Claude reviewed this PR and found no blocking issues, but assessed it as complex — human DEV review is still required before merging. |
pravusjif
left a comment
There was a problem hiding this comment.
The struct approach seems a lot more maintainble to me, nice job 👍
PR 7835PR number: 7835 Intel Core i3Change samples: 2672
|
|
PR reviewed and approved by QA on both platforms following instructions. ✅ Tested in
Scenarios:
Player B enters, gets the cone, and leaves the trigger area; the cone disappears.
Player B enters the trigger area, gets the cone.
Player A enters the trigger area, gets the cone. Windows: Player A PR-7835.player.A.windows.mp4Mac: Player B PR-7835.player.B.-.Mac.mp4 |
Pull Request Description
What does this PR change?
Fixes a use-after-pool-release bug in TriggerAreaHandlerSystem that caused trigger area events to report incorrect entity IDs when multiple players were inside the same trigger area. Addresses #7662.
Root cause: PropagateResultComponent pools and reuses PBTriggerAreaResult.Types.Trigger objects. The prepareMessage callback passed to AppendMessage copies a reference to the pooled Trigger object into the CRDT message. The Trigger was then immediately
released back to the pool after each event. When processing multiple players in the same frame, the next event would reuse the same Trigger object from the pool, overwriting the previous CRDT message's Trigger.Entity field (e.g., remote player ID 32 gets
overwritten with local player ID 1). By the time CRDT serialization runs, all pending messages point to the same Trigger instance holding only the last-written entity ID.
Fix: Deferred pool release — Trigger and PBTriggerAreaResult objects are now enqueued and only released after all trigger area queries have completed. This ensures each AppendMessage call references a unique Trigger object that remains intact until CRDT
serialization. The pools are now created and owned by the system itself (not injected), with proper disposal in OnDispose().
Test Instructions
[QA] SDK Triggers | Trigger areas glitch with multiple users simultaneously #7662
Quality Checklist
Code Review Reference
Please review our Code Review Standards before submitting.