This is using Unity version 2022.3.17f1
This is a VR project created for a VR class :3
Asset name (folder in Assets) - description
- XR Interaction Toolkit (Samples/XR Interaction Toolkit) - base toolkit for developing XR apps for Meta Quest in Unity
- TextMeshPro (TextMesh Pro) - Text formatting and layout
- Quick Outline (QuickOutline) - Used for outlining objects
- EzySlice (EzySlice) - Used to slice meshes using a plane
- Food Props (AddOns/Mg3D_Food) - Simple food objects, from official Unity Assets
- Simple Foods (AddOns/Simple Foods) - More food models that includes both cooked and uncooked versions of the foods, from official Unity Assets
- HQ Kitchen Rusty Knife (CustomShapes/blender/knife.blend) - Used as a base model for the knife, applied custom materials
- NoirMat Marble Pack Vol 1 (NoirMarblePack01) - Texture for walls
- PBR Tile Texture Floor (pbr_textures) - Texture for floor
All files from blender are stored in Assets/CustomShapes
. This folder has 2 subdirectories: blender
and textures
. The blender
folder is where all .blend
files should be placed. The textures
folder is where exported textures are placed (see below). All models imported into Unity should be in the main CustomShapes
folder, in the FBX format.
- Export textures from Blender to Unity: https://www.youtube.com/watch?v=yloupOUjMOA
The main character and setup will just be copied to other scenes, as it has everything needed already. Here's a rough outline of everything that it has:
The only thing that is disabled is the Ray Interactor
. This is currently re-enabled only on pause mode using the following code:
[SerializeField]
private GameObject leftRayRef;
// ...And later
leftRayRef.SetActive(false);
where the leftRayRef
references the disabled Ray Interactor
object shown above.
TODO: Make everything else non-interactable by the ray interactors except the UI
The game master object is used as a global state machine. See the test states for a demo of the states. The text document will list out the states in the following format:
<state_name> [value]
Some states, such as the cutting action, need an additional value to qualify its state change (eg. we need to check for cutting a tomato and not a pear).
The game master will only increment the current state if the valid state change event gets triggered, and this is checked when called.
- Create an empty game object (can be named anything but for this ex we will name it
Game Master
) - Add the
Game Master
script - Fill in the "State File" field with the name of the state file; this should be placed in the
Assets/Resources
folder, with the.txt
extension -- however you do not need the extension for the field - see the guide on Text Asset - If you want to visually see the game state, create a UI Text element (on a UI panel - see the TestScene) and attach it to
Game Master
script
For each object that is the target of a state update (ie. the fridge door opening or the grabbing of a specific object), you will need to attach the State Change
script. You need to assign the Game Master
object to the "Game Master" field and put the state name in the "State Name" field. Note that this state name needs to match the names you put in your state file.
The State Change
script has a Change
string function that can be called. This is how you send a change event to the game master object. This can be called in many different ways; here are a few:
Grabbable Object
Add the State Change
script to the object. Under the XR Grab Interactable
Script, under Interactable Events
(at the very bottom), add the current object's state change script and called the Change function. Like the following example with a fork:
Custom event on script
As with above, I added the State Change
script to the object. For the knife script, I added a custom event field:
[SerializeField]
private UnityEvent<string> onSlice;
and called it with
onSlice.Invoke(collision.gameObject.name);
I selected the dynamic string
option (see Dynamic calls), with will programatically send a parameter (ex. the knife will pass whatever it cut as the parameter). Here's the configuration in the Unity UI:
Call in script
As with before, add the State Change
script. Also add a custom script (here it's DoorOpenDetection). With this script, we can just call the Change
function from the script, passing in the value as a parameter:
GetComponent<StateChange>().Change("");
This basically just uses the XR Grab Interactable
scripts. You can create a simple grabbable object using GameObject > XR > Grab Interactable
. However, you simply need to add the XR Grab Interactable
and XR General Grab Transformer
to any given object.
This interaction uses a library mainly (see above). The cut plane is currently determined by the plane of the knife. There is a small delay between cuts (to prevent glitching), but there is no limit on how small cuts can be (shoud fix).
The knife will cut all objects that have the ingredient
tag on it. The seperation
field on the script determines how far the 2 cut pieces will end up.
TODO: Need to clean up objects that are cut and rename/recenter em
There is a Door (just a rectangle) which has a Hinge Joint. This joint is configured with Use Limits
checked and positioned on its hinge axis.
The handle is a custom object made in Blender (found here). This object is attached to the door using a Fixed Joint. The handle also has the required Grab Interactable scripts attached to make it grabbable. Note that the movement type must be Velocity Tracking otherwise it will not work right.
The actual fridge container is also a custom blender object (Hollow Box) and has nothing special except for a mesh collider.
The pause menu listens for user input using the XRI Default Input Actions, modified to add a menu button interaction (see the input actions file).
The menu is a canvas with text and button elements on it, which will have its position set to the user and its rotation set to where the user is facing, level with the player's vertical position.
All ingredient objects need the following to work properly with cutting and cooking interactions:
- Tagged with the
ingredient
tag - Mesh Collider with the
Convex
variable set to true - State Change script with
Game Master
assigned - Ingredient script with
Inner Material
,Expected Pieces
,Total Cooking Time
, andOvercooked Time
set - Outline script, with
Outline Color
set andAudioClip
set to the button pop (done cooking sound)
There is a script called Container Pickup
. This script allows for items to follow containers and move with them. The way it's done is it will just make the ingredients in the containers the children of the containers. Thus, it will move WITH the container when the container is grabbed. There are a few things to set up to make this work:
- Container must have a Rigidbody, XR Grab Interactable, and XR General Grab Transformer
- Container must have a Collider (with
Is Trigger
checked) that is the area that you want objects to stay in when grabbed - Add the Container Pickup script
- Set the
Select Entered
andSelect Exited
to theContainerPickup.Grab
andContainerPickup.Ungrab
functions respectively