Loot — Unity Integration¶
Folder Overview¶
The scene half of Loot.
LootRoller needs nothing from a scene. LootService exists for everything that does: resolving which adapters are present, running owner-chain modifiers, and handing awards to Inventory, Currency or Pickups.
Purpose¶
This is the component you place, wire, and call. It is the only part of Loot that knows a scene exists.
Rolling and granting are kept apart on purpose: you can verify a table's odds in an EditMode test with no LootService anywhere, and you can grant an award that was rolled somewhere else entirely.
What Lives Here¶
LootService¶
Roll a table, adjust the result, deliver it.
Inspector wiring is three optional adapter slots — inventory, currency, pickup spawner — plus a default container name and a toggle for spawning awards into the world rather than granting them directly.
Key entry points are Roll (produce a result) and RollAndGrant (produce and deliver). Determinism is opt-in through UseDeterministicRng(seed).
Important Notes¶
Every award ends up somewhere, and one of the three places is a report¶
An award is delivered to the owner, spawned into the world, or named in Undelivered. There is no fourth outcome and nothing falls through.
That third case is the one worth knowing about, because it is ordinary rather than exceptional. A full container, or a currency award in a project with no Currency system installed, produces a perfectly valid roll with nowhere to put it. Reporting it lets your game decide — mail it, queue it, tell the player, drop it on the floor. Discarding it silently would look identical to bad luck.
Adapters are optional and their absence does not change the roll¶
A project with only Inventory installed rolls currency awards exactly as a full project does. What changes is where the award can land, never what was won. That keeps a table's behaviour a property of the table rather than of the project it happens to be in.
Adapter references are re-checked for liveness on every use¶
The adapter fields are interface-typed, and Unity's destroyed-object reporting lives on the == operator of UnityEngine.Object. An interface reference never reaches it, so a cached _currency != null stays true forever after the component behind it is destroyed.
This is reachable without misconfiguration — a DontDestroyOnLoad bootstrap holding scene-local adapters hits it on the first scene change. The service therefore reads adapters through liveness- checked properties rather than the fields directly. If you cache an adapter reference in your own code, it needs the same treatment.
Modifiers come from the owner's parent chain¶
ILootModifier implementations are collected with GetComponentsInParent and applied in Priority order, lowest first, ties in component order. Adding the component is the whole wiring step.
They adjust awards, not odds — see Abstractions for why.