Multiplayer Cooking & Assembly System Implementation
This document outlines the architecture and implementation of our AAA-standard multiplayer cooking and assembly system.
Built for extreme network performance, this system utilizes a Data-Driven Architecture. Instead of parenting networked GameObjects to one another (which causes massive bandwidth bloat and lag), the system syncs a lightweight, fixed-size data struct (NetworkItemData.cs) and dynamically updates purely visual meshes on the client side.
Core Architecture Overview
The system is split into three distinct layers:
- The Data Layer: Dictates what an item is, using integer IDs instead of strings.
- The Visual Layer: Purely cosmetic 3D models with NO physics or network logic. Used when items are held by players or sitting on counters.
- The Physical Layer: Heavy GameObjects with Rigidbodies, Colliders, and NetworkTransforms. Used only when items are dropped on the floor.
Core Scripts & Files
| Script | Responsibility |
|---|---|
NetworkItemData (Struct) | A fixed-size struct (zero memory allocation) containing a Base ID, 5 ingredient slots, and an IsOpen state. Sent over the network instead of GameObjects. |
ItemSO (ScriptableObject) | The permanent data template for an item (Name, Icon, Category, Visual Prefab, Physical Prefab). |
ItemDatabaseSO | Assigns a permanent ushort Network ID to every ItemSO for ultra-cheap network syncing. |
InventoryManager | Holds a SyncArray<NetworkItemData> representing the player's pockets/hands. |
Item.cs | Attached to physical floor prefabs. Holds the NetworkItemData struct so burgers don't lose their ingredients when dropped. |
DynamicMealVisuals.cs | Sits on complex visual prefabs (like a Bun or a Box). Reads the NetworkItemData struct and turns child meshes ON/OFF depending on the ingredient IDs inside the struct. |
ClearCounter.cs | The assembly station. Allows players to combine single ingredients from their hand into the NetworkItemData struct resting on the counter. |
🍔 Tutorial: Building a 10-Item Burger Box
This guide walks you through creating a complex, interactable container (a Burger Box) that requires a base item (Bottom Bun) and can hold up to 10 distinct ingredients.
Step 1: Create the Data (ItemSO)
- In Unity, right-click and create your
ItemSOassets:BurgerBox(Set Category toContainer)BottomBun,CookedMeat,Cheese,Tomato,Salad,Onion,Pickles,Bacon,Sauce,TopBun.
- Open your ItemDatabaseSO and add all these items to the list so they receive a unique
ushortNetwork ID.
Step 2: The Visual Prefab (BurgerBox_Visual)
The Visual Prefab is responsible for making the item look good when sitting on a counter. It contains all possible ingredients nested inside it, hidden by default.
- Create an empty GameObject named
BurgerBox_Visual. - Add the Box Bottom Mesh and the Box Lid Mesh as children.
- The Nesting Trick: Add a new empty child object called
Burger_Visuals_Root. - Drag the 3D meshes for all 10 ingredients (Bottom Bun, Meat, Cheese, etc.) inside
Burger_Visuals_Root. Stack them perfectly so they look like a finished burger. - Deactivate (Turn OFF) all the food meshes.
- Add Components to the Root (
BurgerBox_Visual):- Animator: Assign an Animator Controller with an
IsOpenboolean parameter. - ContainerVisuals: Drag the Animator into this script.
- DynamicMealVisuals: * In Required Base Item, assign the
BottomBunItemSO. (This prevents players from putting a loose tomato directly into the box).- In the Ingredient Mappings array, create 10 elements. Map each
ItemSOto its corresponding child mesh in the hierarchy.
- In the Ingredient Mappings array, create 10 elements. Map each
- Animator: Assign an Animator Controller with an
Step 3: The Physical Prefab (BurgerBox_Physical)
This prefab is spawned when the player presses the drop button. It requires physics to fall to the floor.
- Duplicate the
BurgerBox_Visualprefab and rename it toBurgerBox_Physical. - Keep the entire visual setup (the meshes, the
DynamicMealVisualsscript, the Animator). - Add Physics & Network Components:
- Rigidbody: Enable 'Use Gravity'.
- BoxCollider: Scale it to encapsulate the closed box.
- Network Transform: To sync its physical position when kicked or dropped.
- Item.cs: * Drag the
BurgerBoxItemSO into theStarting Item Dataslot.- Drag the Rigidbody into the
Item Rigidbodyslot. - Drag the attached
DynamicMealVisualscomponent into theMeal Visualsslot.
- Drag the Rigidbody into the
Step 4: Link Data to Prefabs
- Go back to your
BurgerBoxItemSO in the Project folder. - Drag
BurgerBox_Visualinto the Visual Prefab slot. - Drag
BurgerBox_Physicalinto the Physical Drop Prefab slot.
Step 5: Test the Gameplay Loop
- Spawn the Box: Place a Box Dispenser in your scene. Interact to get the Box.
- Place the Box: Interact with an empty
ClearCounter. TheBurgerBox_Visualspawns. Because it's aContainer, the counter automatically setsIsOpen = true, playing the open animation. - Assemble: Dispense your ingredients. You must place the
BottomBunfirst (due to theRequired Base Itemrule). Then, stack the Meat, Cheese, and Tomatoes. TheDynamicMealVisualswill turn on the meshes inside the box. - Close the Box: Look at the box with empty hands and press
InteractAlternate(F). The counter updatesIsOpen = false, and the lid animation plays. - Drop it: Pick up the closed box and press
Drop(Q). TheBurgerBox_Physicaldrops to the floor. BecauseItem.csholds the struct, it remembers the box is closed, and it remembers exactly which 10 ingredients are inside it!