Virtual Reality Oral Surgery
A VR based training game for a dentist student.

Background
Virtual Reality Oral Surgery (VROS) Simulation aims to provide an effective, efficient, and economical method for training and practice for medical students, surgeons, and professionals, enabling oral surgery experience in a safe environment. They can also practice a new technique or refresh dormant skills.
Platform | Engine | Project | Time Frame | Role |
---|---|---|---|---|
PC | Unity | VR Commercial Project | 2 Months | Fullstack |
It was my first VR project with Unity. Comparing video games or mobile games, it was much harder to implement particular parts such as UI and input development. Besides, the game needed at least 90FPS to ensure players wouldn't get dizzy. As a result, I needed to deal with some simple performance tuning, such as counting how many polygons would be drawn for one scene and how big those textures would be. In addition, I made a mini framework to help me define "step", "state", and "objective", which allows me to simplify the development a lot.
My Tasks Outline
- UI Design
- Tailored made for VR - Gameplay Implementation
- Created a state and step system to simplify the development
Highlights
Custom VIVE Controller UI
I developed a custom VIVE controller UI with Unity that allows players to use the touchpad on the VIVE controller to select a menu with a simple touch and click. The receipt behind this is quite simple. I used the touch position from the VR device API and calculated how many sectors were in the menu. After that, use the position to calculate which sector players are pointing to.

Code snippets
The update calls for getting the position from the VR Controller and setting it to the checker.
if (trackedEvent.padTouched) {
if (!cursor.gameObject.activeSelf) {
cursor.gameObject.SetActive (true);
}
ClickedEventArgs e;
e.controllerIndex = trackedEvent.controllerIndex;
e.flags = (uint)trackedEvent.controllerState.ulButtonPressed;
e.padX = trackedEvent.controllerState.rAxis0.x;
e.padY = trackedEvent.controllerState.rAxis0.y;
cursor.SetPosition (e.padX * cursorAreaRidus, e.padY * cursorAreaRidus);
} else {
if (cursor.gameObject.activeSelf) {
cursor.gameObject.SetActive (false);
}
}
In the VRCursor class, the update call will get all clickable buttons on the menu and auto-focus the smallest distance from the touch position.
if (isReady) {
// Clear result list
resultList.Clear ();
// Calculate all the distances
float dist;
for (int i = 0; i < targetList.Count; i++) {
if (targetList [i].gameObject.transform.parent.gameObject.activeSelf) {
dist = Vector3.Distance (transform.position, targetList [i].transform.position);
resultList.Add (dist);
} else {
resultList.Add (float.PositiveInfinity);
}
}
// Find Min Index
int minIndex = Helper.FindMinIndexFromList (resultList);
// Cursor Callback
OnChangedNearestPadButton (minIndex);
}
Technologies Used
- Unity
- 3DsMax
- Visual Studio
- VR / HTC VIVE
Screenshots




