Player Tracking Description

Player tracking is a method for knowing where a player is inside the world. These methods are entirely local and need to be combined with other techniques in order to sync an object between all clients. There are 3 currently known types of player tracking: Player camera tracking, which tracks the player's head, player base tracking which tracks the player's feet and collider, and player playspace tracking which tracks the location of the player within their VR playspace.


Image of the 3 different types of tracking

Player Camera Tracking

The first form of player tracking and still the most used version is player camera tracking. Originally discovered by HardLight using the combat system but later updated to use UI Canvases. This allows the world creator to know exactly where the local player's camera is located. There are two methods currently to get the player's camera location. The original method was the combat system, but this method should be avoided and the newer canvas method should be used instead.

Canvas Method

You can use a UI Canvas and VRC_UIShape to track the player's camera position. Simply using these two components will have the tracker update at the end of the frame, making everything that relies on its position be a frame behind. It will work for most needs, but if you need the tracker to update on the frame, see HardLight's Toybox prefabs or CyanLaser's video tutorial.


  1. Right click the hierarchy, and create a new UI Canvas. Delete the Canvas Scaler component and Graphics Raycaster component.
  2. In the canvas, change the render mode to "Screen Space - Camera" and drag in the main camera to the Render Camera slot.
  3. Set the plane distance to 0. Note that this will set the scale of the canvas to zero and all children objects will be invisible. See Toybox prefab for a version that does not scale children.
  4. Add the VRC_UIShape component to your canvas object.
  5. Add and disable a box collider. Without this, the VRC_UIShape will add one and it will collide with objects in the world.

TODO Explain how to force the canvas update to allow for lateupdate trackers

Combat System Method

The Combat System was the first known method for player tracking. It used the visual damage prefab as a reference to knowing where the camera is. This tracking is more accurate and even gives you the player's camera scale (useful for Real Height setting detection) but comes with the issues of the combat system such as rigidbodies on avatars breaking. It is recommended to use the canvas approach to not break avatars. This version of player tracking can be found in Toybox V1 if a link still exists.

Player Base Tracking

The player's base is the location of the player's feet and player capsule collider. While most of the time the player's base is facing the same direction as the player's camera, there are certain angles which will cause them to deviate. Be careful when using the rotation of the player base.

AutoCam Method

The first attempt at player base tracking was using the standard asset script AutoCam's auto target player option. While this does work to find a player, you are not guaranteed to find the local player, making this an impractical method for multiplayer worlds.

Teleport Method

PhaseDragon figured out that using the TeleportPlayer trigger in combination with player camera tracking, you could use vector math to calculate the player base location. He used this method to create a seamless teleport and made a non euclidean map where walking down hallways would lead to areas that did not make sense with relation to the layout. CyanLaser tried to recreate this setup, but in the process realized that you can teleport the player every frame, getting the player base location and teleport them back without the player realizing. With this, usable player base tracking was discovered which allows for alternate locomotion methods.

How it works

The way player base tracking works is by teleporting the player to a known point and calculating the offset, and then teleporting the player back. We start off only knowing where the player's camera is and the teleport point.

  1. Save the current camera point
  2. Teleport the player to a known point
  3. Save the offset between the camera point and the known point
  4. Add offset to previous camera point to get previous base location
  5. Teleport player back to base location

Bad diagram showing vector math



Player base tracking requires a player camera tracker to work properly. It is recommended you have knowledge on UI Events and how to force order of operations with them. Having Merlin's Easy Event Editor script will also make the process of creating this much easier.

For this, you will need the player camera tracker, 3 objects for calculating the vector math, and one button to perform the actions in order.

  1. Create a single GameObject that will be used for our known position. Call this "TeleportPoint".
  2. Create 3 GameObjects all in a chain with the "CameraPosition" as the main parent, "TmpCameraPosition" as a child of "CameraPosition", and "PlayerBase" as a child of "TmpCameraPosition"
  3. On "CameraPosition", add VRC_SceneResetPosition script and set the position as the Player Camera Tracker
  4. On "TmpCameraPosition", Add two VRC_SceneResetPosition scripts. Set the first also to the Player Camera Tracker and set the second to the "CameraPosition" object.
  5. On "PlayerBase", add VRC_SceneResetPosition script and set the position to "TeleportPoint".
  6. Create a new GameObject to be used as our update loop. Call it "UpdatePlayerBase". Add a UI Button and EventSelectorAlways (This is a premade animation included in Toybox that will call the UI Button's press method every frame. See UI Events for more details)
  7. Also on this update object, add a VRC_Trigger.
  8. Add two Custom Triggers, each with the local broadcast type and a Teleport Player action.
  9. In the first custom trigger, name it "TeleportPlayerBase" and set the teleport location to "TeleportPoint"
  10. In the second custom trigger, name it "TeleportBackPlayerBase" and set the teleport location to "PlayerBase"
  11. In our "UpdatePlayerBase" button, you will need to add 9 events.
  1. Find the Player Camera Tracker's update button and call Press() on it. This will ensure that the player tracker is in the correct position.
  2. Call "CameraPosition" VRC_SceneResetPosition.ResetPosition() method. This will save the current location of the player's camera.
  3. Call "UpdatePlayerBase" VRC_Trigger.ExecuteCustomTrigger("TeleportPlayerBase"). This will teleport the player to the known location.
  4. Call Press() on the Player Camera Tracker again to update the tracker's position.
  5. Call "TmpCameraPosition" VRC_SceneResetPosition(1).ResetPosition() method. This will move the object to the new camera position, allowing us to get the offset between the camera and the known location. The (1) here represents the first VRC_SceneResetPosition script on this GameObject. Use Merlin's EasyEventsEditor to easily access multiple scripts of the same type on a GameObject.
  6. Call "PlayerBase" VRC_SceneResetPosition.ResetPosition() method. This will save the offset from the Player's camera to the known location.
  7. Call "TmpCameraPosition" VRC_SceneResetPosition(2).ResetPosition() method. This will move our temporary camera location back to the previous camera location, while keeping the offset. Again the (2) here represents the second VRC_SceneResetPosition script on this GameObject.
  8. Call "UpdatePlayerBase" VRC_Trigger.ExecuteCustomTrigger("TeleportBackPlayerBase"). This will teleport the player to the player base offset we calculated, which will be the exact location they started in.
  9. Call Press() on the Player Camera Tracker again to update the tracker's position so that it is in the correct location at the end of all the teleporting.

Note that by applying small offsets to the "CameraPosition" before step 8, you can force the player location. This is the main technique used in Alternate Locomotions such as climbing.
As mentioned before, be careful when using player base rotations with offsets. It has the small chance of forcing the player to look in a direction which will feel terrible in VR.

TODO Make Cyan release a prefab of this and player playspace tracking

Player Playspace Tracking

Player playspace tracking is finding the location of the local player's vr playspace center relative to where they are in the world. By itself, this does not seem useful, but due to weird rotations in the player base, this is very helpful for alternate locomotions such as climbing.

Player playspace tracking is found in the same way as player base tracking, but when using the teleport player trigger, make sure to set the align room to True instead of False for both teleports.

Uses of Player Tracking

  • Player indicators
  • Hats
  • Minimap
  • AI looking at and targeting players
  • Alternate locomotions

Additional Explanation and Diagrams

These diagrams will start off with everything in a pile for simplicity's sake. The green sphere is the "CameraPosition" object, the blue sphere is the "TmpCameraPosition" object, the red cube is the "PlayerBase" object, and the white capsule is the "TeleportPoint" object.
These object names are in reference to the objects described earlier in the setup section of this page.


At the beginning of the update loop our setup looks something like this:


Currently we haven't done anything, so everything is just in a pile and fred is hanging out being bored.

For the next step we execute events 1 and 2 in the "UpdatePlayerBase" button. That will make sure the camera tracker gives us the current position of the player's camera, then we will more the green sphere, the "CameraPosition" object, to that position.


Now the green "CameraPosition" sphere is on fred's face, so that's a start.

Now we execute event 3, that teleports the player to the "TeleportPoint" white capsule. As it happens, when you teleport a player they are teleported so that their base is at the position where you teleported them to.


Not much changed, fred is just moved to the teleport point, note that the green "CameraPosition" object didn't move.

Events 4 and 5 are executed now, this is the same as events 1 and 2, but with a different camera object now. Event 4 updates the camera tracker to the player's current head position and event 5 moves the blue sphere, the "TmpCameraPosition" object, to that position.


So now we have the old camera position and also the new one, and we also know that fred's base position is at the teleport point.

Up next we have event 6. This moves the red cube, the "PlayerBase" object, to the "TeleportPoint" object because as I mentioned before, when you teleport someone their base position is aligned with the object that you teleported them to. Now by moving the "PlayerBase" object we can get the offset between the player's head and their base, this is because "PlayerBase" is a child of "TmpCameraPosition" so the distance between them is the distance between the player's head and the player's base.


At this point we are nearly done, we have the old camera position, the new camera position, as well as the offset between the player's base and their head.

Event 7 is executed now, which moves the "TmpCameraPosition" object back to the same position as the "CameraPosition" object that we recorded before. When that happens the "PlayerBase" object object is also moved because it is a child of the "TmpCameraPosition" object, and when it is moved it keeps the same offset that we just gave it before. Which means that the "PlayerBase" object is now where the player's base was at the start of this whole thing.


With this we finally know where the player's base position is, its that red cube on the left.

So that's not quite right, the red cube is actually at the position where the player's base was but currently our player, fred in this example, is still over at the "TeleportPoint" This is where event 8 comes in. what event 8 does is teleport the player the the "PlayerBase" that we just found and when that happens the player will be right back where they started.


So now we know where the player's base position is and the player is back where they started.