Generating items
One static call, one request object, one plain-data result. Seeds make it deterministic; a callback chain makes it yours.
The request
var request = new ItemGenerationRequest { Template = doombringerTemplate, // optional — pins name/icon/forced affixes ItemType = weaponType, // required when no template SubType = swordSubType, // optional refinement Rarity = legendaryRarity, // required, always Seed = 1337, // same seed → same item Settings = generatorSettings, // supplies the affix pool + name config }; ItemInstance one = ItemGenerator.Generate(request); ItemInstance[] lot = ItemGenerator.GenerateBatch(request, 12); // a chest
When a template is set, its type and sub-type win over whatever the request carries. Batch generation derives a distinct deterministic seed per index from the base seed — twelve different items, all reproducible from one number.
null with a console warning — no exception. Null-check every result. The two hard requirements: a resolvable item type (directly or via template) and a rarity.What comes back
| ItemInstance property | Type | Description |
|---|---|---|
| ItemName / Description / RarityTypeLabel | string | Composed name, template description, and the “Legendary Sword”-style label. |
| ItemType / ItemSubType / Rarity | refs | The definitions that produced it. |
| Icon / Prefab | Sprite / GameObject | Resolved template → sub-type → type. |
| BaseStats / ImplicitModifiers | StatModifier[] | Rolled core stats and always-on implicit rolls. |
| RandomAffixes | GeneratedAffix[] | Forced template affixes first, then the random picks — each with its rolled stat values. |
| SocketCount | int | Rolled from the rarity’s range. A count — socket contents are your game’s domain. |
| LegendaryEffect | LegendaryEffect | Present when the template supplies one and the rarity allows it; look up its EffectId in your gameplay code. |
| SellValue / MaxDurability / MaxStackSize / ItemLevel | int | Economy numbers (formulas below). ItemLevel is metadata only. |
| GenerationSeed / GeneratorVersion / GenerationTimestamp / SourceTemplateName | audit | Everything needed to reproduce, version-check, or trace the roll. |
It's a plain [Serializable] class — no MonoBehaviour, no scene dependency. For storage, though, use snapshots rather than serializing it directly (see Saving generated items).
Seeds & determinism
The RNG is Unity.Mathematics.Random — deterministic across platforms. The contract: same seed, same definition assets, same generator version ⇒ bit-identical item. That enables reproducible chests (world seed + chest position → contents), player-reported bugs you can replay from one int, and the entire persistence model.
// The player's screenshot shows seed 8842217 on an Epic Mystic_Staff. var repro = ItemGenerator.Generate(new ItemGenerationRequest { Template = mysticStaff, Rarity = epic, Seed = 8842217, Settings = settings, }); // → the exact same rolls, affixes, sockets, and name.
GeneratorVersion (currently 2). When generation logic changes between asset versions, old seeds can roll differently — the version stamp is how saved snapshots detect and warn about that instead of silently drifting.The post-generate hook
Every generated item flows through ItemGeneratorCallbacks.OnPostGenerate before it's returned — subscribers receive the instance and return it (possibly modified), chained in subscription order. It's the sanctioned place for seasonal bonuses, difficulty scaling, or analytics taps:
using ItemGeneratorSystem; public static class SeasonalBonus { public static void Enable() => ItemGeneratorCallbacks.OnPostGenerate += Apply; public static void Disable() => ItemGeneratorCallbacks.OnPostGenerate -= Apply; static ItemInstance Apply(ItemInstance item) { item.SellValue = (int)(item.SellValue * 1.25f); // harvest-festival prices return item; } }
static — it survives scene loads and domain reloads in the editor. Always unsubscribe (and keep handlers deterministic if you rely on seed reproduction, because they re-run on snapshot restore).Value & durability formulas
SellValue = floor(baseValue × rarity.SellValueMultiplier × (1 + 0.1 × affixCount))
MaxDurability = floor(baseDurability × rarity.DurabilityMultiplier)
baseValue / baseDurability come from the sub-type or type (defaults 10 / 100),
optionally overridden per template. Every affix adds +10% to sell value.