Skip to content

Crafting — Workbenches

This folder contains trigger-based crafting benches for both 2D and 3D scenes.

Workbenches allow players to walk up to a station, hold a key, and enqueue crafts directly in-game without any custom UI. They are optional helpers designed for demos, prototypes, and quick testing — not required for production use.

Everything here reflects actual runtime behaviour, with additional Editor-only guardrails and teaching conveniences clearly isolated.


🎯 Purpose

Workbench components provide:

  • Ready-made, interactive crafting stations
  • Automatic integration with input, recipes, and CraftingServiceCore
  • Separate 2D (Collider2D) and 3D (Collider) variants
  • Hold-to-craft behaviour with configurable repeat cooldown
  • Full respect for:
  • modifiers
  • validators
  • station tags
  • routing
  • XP
  • concurrency limits

Workbenches are thin orchestration helpers — they do not add new crafting rules and are not an integration or extension surface.


🌐 Multiplayer & Authority

Workbench components are authority-aware but netcode-agnostic.

By default (serverOnly = true):

  • Preflight (CanCraft / CanCraftDetailed) may run anywhere (client or server)
  • Mutation (Enqueue) is permitted only when authority allows

Authority Resolution Order (Exact)

  1. ICraftingBenchAuthority assigned directly to the bench
  2. ICraftingAuthority assigned to CraftingServiceCore
  3. If neither exists → enqueue is denied

This makes workbenches safe for:

  • Single-player projects
  • Server-authoritative multiplayer (NGO, Mirror, Fusion, custom RPCs)

⚠️ Workbenches do not perform networking.
In multiplayer, they should be executed on the server/host or guarded by an authority implementation.


⚙️ Included Benches

CraftingWorkbench2D

  • Uses OnTriggerStay2D to detect presence
  • Hold the craft key (default: F) to enqueue the selected recipe
  • Supports repeated crafting via repeatCooldown
  • Optional stationTagFilter restricts which recipes may be crafted
  • Uses the entering collider’s GameObject as the craft owner

CraftingWorkbench3D

Identical behaviour to the 2D variant, with additional owner resolution logic:

  1. If preferTaggedPlayerOwner is enabled and a GameObject tagged "Player" exists → it is used as the owner
  2. Otherwise, prefer other.attachedRigidbody.gameObject
  3. Fallback to other.gameObject

This matches common player-controller setups without requiring custom glue code.


🧩 Recipe Resolution (Supported API Only)

Workbench recipe fields are typed as:

[SerializeField] ScriptableObject[] recipes;

At runtime, each recipe is resolved exclusively via the supported public API:

RecipeResolve.ResolveOrNull(scriptableObject);

Behaviour:

  • If the asset is a RecipeCore, it is used directly
  • If the asset is a Unity-facing wrapper (e.g. RecipeDefinition):
  • Conversion succeeds only when the relevant optional systems are present
  • Otherwise resolution returns null
  • If resolution fails:
  • The craft is rejected safely
  • Editor warnings may be logged for visibility

Workbenches do not call RecipeCache or ToCore() directly.
All conversion, caching, and optional-system logic is intentionally hidden behind RecipeResolve.


⌨️ Input Handling

Craft input is resolved in this order:

  1. If inputServiceComponent implements IInputService
    → that service is used

  2. Otherwise:

  3. In Editor or with RAB_DEMO defined → fallback to DebugKeys
  4. In player builds, with no input service → no input is processed

⚠️ In production builds, an IInputService must be supplied for benches to respond to input.

Input is checked every trigger frame while the player remains inside the collider.


🧱 Editor Guardrails

Workbench components include Editor-only validation and warnings:

  • Enforce collider.isTrigger = true
  • Warn if:
  • recipe list is empty
  • recipeIndex is out of range
  • stationTagFilter does not match the selected recipe’s station tag
  • a recipe asset cannot be resolved in the current build configuration

All guardrails run only in the Editor.


🧩 Station Tag Behaviour

Workbenches supply explicit preflight options:

var opts = new CraftPreflightOptions(null, stationTagFilter);

This means:

  • ctx.stationTag is forced to stationTagFilter during preflight and enqueue
  • If stationTagFilter is set and does not match the recipe’s own StationTag, the bench rejects the recipe before preflight

This allows benches to act as explicit station-gated crafting points while still respecting recipe metadata.


🔄 Usage Flow

  1. Add a 2D or 3D workbench to the scene
  2. Assign (or auto-resolve) a CraftingServiceCore
  3. Provide one or more recipe assets
  4. Player enters the trigger and holds the craft key
  5. Bench performs:
  6. CanCraft(owner, recipe, opts)
  7. Authority check
  8. Enqueue(new CraftRequest(...))

All CraftingServiceCore behaviour applies automatically:

  • Modifiers
  • Validators
  • Routing
  • Currency rules
  • XP rules
  • Concurrency limits

💡 Notes

  • Workbenches are optional helpers — not required for gameplay
  • Ideal for demos, prototypes, and test scenes
  • Production games typically drive crafting from custom UI
  • Workbenches exercise the entire Crafting pipeline without additional glue code

Workbenches provide a practical, low-friction way to interact with the full Crafting system while keeping all authoritative logic inside CraftingServiceCore.