Pico VR Development Notes (Basics)
XR Interaction Tooikit Version 2.3.2
1. Environment setup
In fact, the official document has been written in great detail. Here is just a quick setup without any nonsense. There is another official explanation that is wrong. I would like to add some explanation in the development tools section.
Plug-in installation - install pico's sdk and XR Interaction Tooikit
Environment configuration - add headsets and controllers to the scene, and perform configuration and project configuration
Development Tools - The streaming development tools provided by Pico can be debugged using controllers and headsets without packaging.
1. Plug-in installation
pico SDK installation
pico SDK download address: SDK - PICO Developer Platform (pico-interactive.com)
After downloading the SDK, unzip it
Open unity→Window→PackgeManager→Add Package From disk (+ in the upper left corner)→select package.json in the decompressed file
XR Interaction Tooikit installation
Search for XR Interaction Tooikit in packageManager
Select a version as high as possible, not lower than 2.1.0.
Open the Samples panel and import Starter Assets , **XR Device Simulator** and Tunneling Vignette .
2. Environment configuration
Scene configuration
Add XR Origin :Hierarchy→Add(upper left corner +)→XR→XR Origin(VR)
Controller settings
-
Select Hierarchy's XR Origin sub-object LeftHand Controller
-
Configure the LeftHand Controller's control XR Controller, click on the preset in the upper right corner, and select XRI Default Left Controller (the right handle is also configured, select XRI Default Right Controller)
-
Select the handle model and select LeftControllerModel(Tranform) in the Model Prefab of the XR Controller
Packaging settings
Select: Edit→Player→settings for Android→other Setting
Minimum API Level Select Android 10.0
Target API Level 选择Automatic(Highest installed)
Scripting Backend Select IL2CPP
Check ARM64
Select: Edit→Project Settings→XR Plug-in Management→Android Standalone Settings→Select PICO
3. Development tools
SDK installation
Download address: SDK - PICO Developer Platform (PICO Unity Live Preview Plugin)
After downloading the SDK, unzip it
Open unity→Window→PackgeManager→Add Package From disk (+ in the upper left corner)→select package.json in the decompressed file
windows download client
Download address: SDK - PICO Developer Platform (PICO Developer Center)
After local installation, the steam streaming tool will be installed.
Enable developer mode for all-in-one machine
- Turn on the PICO VR all-in-one machine.
- Go to Settings > General .
- Ray-align the settings field and click multiple times until Developer Options appears under the left navigation bar.
- Click Developer to enter the developer options interface.
- Turn on the USB debugging switch in the upper right corner .
*There is an error in the official document here. To enable the developer model, you need to click the settings button multiple times.
Project settings
Select: Edit→Project Settings→XR Plug-in Management→ PC Standalone Settings→Select PICO Live Preview
2. Development
1. Handle input
get handle
InputDevice deviceLeft;//左手柄
InputDevice deviceRight;//右手柄
private void Start()
{
deviceLeft = InputDevices.GetDeviceAtXRNode(XRNode.LeftHand);
deviceRight = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);
}
Handle trigger core method TryGetFeatureValue
Handle trigger button trigger
/// <summary>
/// 扳机键
/// </summary>
/// <param name="inputDevice">手柄</param>
/// <param name="action">触发委托</param>
/// <param name="Value">触发参数</param>
void triggerButton(InputDevice inputDevice, ref bool Value, Action action)
{
if (inputDevice.TryGetFeatureValue(CommonUsages.triggerButton,out Value)&&Value)
{
action();
}
}
Trigger key strength
/// <summary>
/// 扳机键力度
/// </summary>
/// <param name="inputDevice">手柄</param>
/// <param name="action">触发委托</param>
/// <param name="Value">触发参数</param>
void trigger(InputDevice inputDevice, ref float Value, Action<float> action)
{
if (inputDevice.TryGetFeatureValue(CommonUsages.trigger, out Value)&& !Value.Equals(0))
{
action(Value);
}
}
grip key
/// <summary>
/// 抓握键
/// </summary>
/// <param name="inputDevice"></param>
/// <param name="action"></param>
/// <param name="Value"></param>
void gripButton(InputDevice inputDevice, ref bool Value, Action action)
{
if (inputDevice.TryGetFeatureValue(CommonUsages.gripButton, out Value) && Value)
{
action();
}
}
Grip key strength
/// <summary>
/// 抓握键力度
/// </summary>
/// <param name="inputDevice"></param>
/// <param name="action"></param>
/// <param name="Value"></param>
void grip(InputDevice inputDevice, ref float Value, Action<float> action)
{
if (inputDevice.TryGetFeatureValue(CommonUsages.grip, out Value) && !Value.Equals(0))
{
action(Value);
}
}
Joystick direction
/// <summary>
/// 摇杆方向
/// </summary>
/// <param name="inputDevice"></param>
/// <param name="action"></param>
/// <param name="Value"></param>
void primary2DAxis(InputDevice inputDevice, ref Vector2 Value, Action<Vector2> action)
{
if (inputDevice.TryGetFeatureValue(CommonUsages.primary2DAxis, out Value) && !Value.Equals(Vector2.zero))
{
action(Value);
}
}
joystick
/// <summary>
/// 摇杆
/// </summary>
/// <param name="inputDevice"></param>
/// <param name="Value"></param>
/// <param name="action"></param>
void primary2DAxisClick(InputDevice inputDevice, ref bool Value, Action action)
{
if (inputDevice.TryGetFeatureValue(CommonUsages.primary2DAxisClick, out Value) && Value)
{
action();
}
}
X/A
/// <summary>
/// X/A
/// </summary>
/// <param name="inputDevice"></param>
/// <param name="Value"></param>
/// <param name="action"></param>
void primaryButton(InputDevice inputDevice, ref bool Value, Action action)
{
if (inputDevice.TryGetFeatureValue(CommonUsages.primaryButton, out Value) && Value)
{
action();
}
}
Y/B
/// <summary>
/// Y/B
/// </summary>
/// <param name="inputDevice"></param>
/// <param name="Value"></param>
/// <param name="action"></param>
void secondaryButton(InputDevice inputDevice, ref bool Value, Action action)
{
if (inputDevice.TryGetFeatureValue(CommonUsages.secondaryButton, out Value) && Value)
{
action();
}
}
2. Ray
How to get rays
XRRayInteractor.TryGetCurrent3DRaycastHit(out hit)
XRRayInteractor
It is the XRRayInteractor script mounted on the controller.
Demo
public XRRayInteractor rayInteractor;
RaycastHit hit;
Vector3 getRayPoint()
{
if (rayInteractor.TryGetCurrent3DRaycastHit(out hit))
{
string name = hit.collider.name;
Debug.Log(name);
return hit.point;
}
else
{
return Vector3.zero;
}
}
Additional settings
Type of ray
type | illustrate |
---|---|
Staight Line | straight line |
Projectile Curve | parabola |
Bezier Curve | Bezier curve |
Modification method
rayInteractor.lineType = XRRayInteractor.LineType.ProjectileCurve;
Different types of rays have their own parameters that can be modified. For example, Stailght Line's MaxRaycastDistance (farthest ray distance) and ProjectileCurve's Additional Flight Time (ray flight time) can be directly assigned.
Effective rays and invalid rays
When the ray touches the triggerable UI or model, the ray is a valid ray, and the feedback uses ValidColorGradient. Otherwise, use InvalidColorGradient.
Invalid rays and valid rays can also return RaycastHit when they touch a collision model. The difference lies in the settings of the XR ray itself, such as the collision Reticle.
To achieve effective collision, you need to add Tracked Device Physics Raycaster script, etc. to the model.
Reticle (crosshair)
Reticle is the point where the ray collides with the model (UI).
Add method:
Find the XR Interactor Line Visual script on the handle, create the Reticle prefab and add it directly.
3. UI trigger
Triggering conditions
To trigger the handle ray to the UI, two scripts need to be mounted on the premise of completing the basic VR scene construction.
Add Tracked Device Graphic Raycaster to Canvas
Replace the Standalone Input Module on the EventSystem with the XR UI Input Module (the Tracked Device Physics Raycaster script added on the model is also affected by the XR UI Input Module)
Precautions
Canvas's Order in Layer is best set to a negative value. If 0 or a positive value, the crosshairs may be obscured by the UI.
When it is 0
When it is -1