Food Fusion
Overview
Food Fusion is a sample of a cooperative party cooking game using Fusion Shared mode. Players are presented with a series of orders to be made and served before they expire. They will chop, cook, and plate ingredients to put together the orders. The sample demonstrates character customization, persistent scene objects, object instantiation, authority transfer, usage of TRSPs, non-destructive player disconnects, and a robust interaction and crafting implementation.
Before You Start
To run the sample, first create a Fusion AppId in the PhotonEngine Dashboard and paste it into the App Id Fusion
field in Photon App Settings (Tools/Fusion/Realtime Settings). Launch the game from the Preloader
scene to play.
Download
Version | Release Date | Download | |
---|---|---|---|
2.0.2 | Sep 04, 2024 | Food Fusion 2.0.2 Build 643 |
Highlights
- Shared state authority of objects
- Drop in, drop out gameplay
- Player nicknames/colour selection
- Extendable generic interaction system
- Extendable ingredients and recipes structure
Objects
The cooking system utilizes scriptable objects to describe the relationships between objects and actions. The object types central to this system have a ScriptableObject component as well as a NetworkObject. All NetworkObjects will reference their ScriptableObject counterpart, if they have one, in a field named Data
. Likewise, ScriptableObjects reference an associated prefab which has the corresponding NetworkObject.
Ingredients
Ingredients are the basis of the system, and may represent a raw or processed form, and may or may not be part of a recipe. Notably, a raw tomato is an ingredient, but needs to be processed to be useful. Similarly, burned food is also an ingredient, but has been over-processed and is no longer useful.
IngredientData : ScriptableObject
references an icon (Sprite
) with which to be represented by in the UI
referenced by: FoodProcess
, Recipe
Ingredient : NetworkObject
The Ingredient has one networked property, ProcessedAmount
. Not all ingredients make use of this, but it is used in processes such as chopping and cooking to track how far along the process is.
Food Processors
Food processors are a requisite for ingredient transformation. They are used in one of two ways; either by a Character, or by an Appliance. How food processors may be used is defined by FoodProcess
assets. Whether they are associated with an appliance is dictated by the ApplianceData
asset.
FoodProcessorData : ScriptableObject
referenced by: ApplianceData
, FoodProcess
FoodProcessor : NetworkObject
Appliances
Appliances are autonomous interactors which process ingredients in a corresponding food processor. They will attempt to interact each tick with a food processor placed on them. Appliances are necessarily associated with exactly one type of food processor.
ApplianceData : ScriptableObject
references a FoodProcessorData
which is valid for use with the appliance
Appliance : NetworkObject
Food Processes
Food Processes (FoodProcess.cs
) are scriptable objects describing any transformation of one ingredient to another. A food process is defined as an input ingredient, an output ingredient, a food processor to be used, and an amount of ticks until the process is finished.
The associated system is the ProcessGraph
.
Recipes
Recipes consist of required ingredients and optional ingredients. They determine which ingredients are valid to mix together. Recipes are also used when generating orders.
The associated systems are the IngredientGraph
as well as the OrderMenu
.
Interactions
Nearly everything that changes the game state stems from an interaction or a chain of interactions. This includes picking up and placing objects, processing ingredients, submitting orders, etc. These interactions are placed on the various prefabs and referenced by an Interactable
component, which has two groups for the types of interactions the player can provide, "Grab" and "Use". The order in these lists determines priority. Only one interaction will be triggered at a time, so priority is important.
There are special "delegation" interactions which have no specific behavior of their own, but instead send the interaction signal to another object.
Systems
A few different systems underpin the operations of the game loop.
AssemblyMap
The AssemblyMap aggregates the AssemblyVisuals and provides composition objects and sprites for certain sets of ingredients.
Used by: FoodContainer
, FoodOrderItemUI
IngredientGraph
The IngredientGraph evaluates all Recipes and provides methods for determining whether a given ingredient is part of any recipes, and whether a given ingredient is compatible with a set of ingredients.
Used by: FoodContainer
ProcessGraph
The ProcessGraph consumes FoodProcesses and supplies information about whether a FoodProcessor and Ingredient are compatible, and what the resulting Ingredient will be and how many ticks it takes to process.
Used by: FoodProcessor
, ProcessFoodInteraction
ResourceBank
ResourceBanks form a set of complimentary key-to-value and value-to-key dictionaries whose keys are used to identify ScriptableObjects over the network. A ResourceBank is implemented in the project via an Ingredient Bank, which holds reference to all IngredientData ScriptableObjects in the project.
OrderMenu
The OrderMenu is initialized with a collection of available Recipes, and provides a valid set of Ingredients which comprise an order, using a random selection of optional ingredients from the Recipe.
Authority Management
State authority of objects in this sample is all routed through instances of the custom behaviour AuthorityHandler
. The public entrypoint is the method RequestAuthority
which takes two optional parameters, an Action to be invoked in the case of a successful transfer, and an Action to be invoked in the case of a failure.
Targeted RPCs are utilized both for requesting authority as well as signalling the outcome of requests. When a request is made, a Guid
is sent as part of the RPC, representing the expected state of the hierarchy for the object in question. When the RPC is received, this state is compared against the state observed by the recipient. In the case of a discrepancy, the request will be rejected. The request will also be rejected if a transfer for that object is already in progress, or if the client does not possess the state authority.
Debugging
Included is a utility to view which player has authority over what objects. This can be toggled on the Main Camera GameObject in the Game scene by enabling the ViewAuthority
component.
Objects whose state authority is a valid player will be outlined in the player's selected color. Objects which have a state authority of a disconnected player will be outlined gray.
Back to topNote that
ViewAuthority
relies on another component,Glint
, which is responsible for drawing commands to the screen.Glint
must be present on the camera object forViewAuthority
to function.