ZenCoder Tips & Tricks: AR / VR
ZenCoder shines in XR workflows — especially when testing interactions, visuals, haptics, and controller behavior without redeploying or recompiling. Everything runs live, and you can adjust, tweak, and validate in real-time.
💡 Important: Before using any of the examples below, make sure you select the correct XR component (like
XRBaseController
,XRGrabInteractable
,XRRayInteractor
, etc.) from the ZenCoder toolbar.
The keywordtarget
will dynamically reflect the selected component and give you full access to its members.
Live Haptic Feedback Test
Selected component: XRBaseController
Disable Input Actions Temporarily
Selected component: XRBaseController
Read Trigger Press State
Selected component: XRBaseController
public void Start()
{
target.inputDevice.TryGetFeatureValue(UnityEngine.XR.CommonUsages.triggerButton, out var isPressed);
Debug.Log("Trigger pressed: " + isPressed);
}
Instant Grab with No Physics
Selected component: XRGrabInteractable
Adjust Raycast Behavior
Selected component: XRRayInteractor
public void Update(float dt)
{
target.maxRaycastDistance = 50f;
target.lineType = UnityEngine.XR.Interaction.Toolkit.XRRayInteractor.LineType.ProjectileCurve;
}
Live Object Rotation While Grabbed
Selected component: XRGrabInteractable
private float t;
public void Update(float dt)
{
t += dt;
target.transform.localRotation = Quaternion.Euler(0f, t * 30f, 0f);
}
Highlight Reticle Switching
Selected component: XRInteractorLineVisual
public void Start()
{
target.reticle = GameObject.Find("CustomReticle");
target.lineWidth = 0.015f;
}
Visualize Camera Gaze
Selected component: Camera
in VR rig
public void Update(float dt)
{
Debug.DrawRay(target.transform.position, target.transform.forward * 5f, Color.cyan);
}
Reposition the Player or XR Rig at Runtime
Want to move your XR Rig without hitting Play every time?
public void Start()
{
target.transform.position = new Vector3(0, 1.8f, 0); // set user at standing height
}
Lock Grabbed Object
Selected component: XRGrabInteractable
public void Start()
{
target.movementType = UnityEngine.XR.Interaction.Toolkit.XRBaseInteractable.MovementType.Kinematic;
}
XR Ray Interactor Debug Visual
Component: XRRayInteractor
public void Start()
{
target.lineType = UnityEngine.XR.Interaction.Toolkit.XRRayInteractor.LineType.ProjectileCurve;
target.maxRaycastDistance = 10f;
}
Real-Time Interactor Layer Tuner
Component: XRRayInteractor
Live Grab Force Adjustment for Physics Feel
Component: XRGrabInteractable
public void Start()
{
target.movementType = UnityEngine.XR.Interaction.Toolkit.XRBaseInteractable.MovementType.VelocityTracking;
target.throwOnDetach = true;
target.throwSmoothingDuration = 0.3f;
}
Instant Grabbable Lock
Component: XRGrabInteractable
One-Hand or Two-Hand Toggle
Component: Custom Component with XRGrabInteractableTwoAttach
public void Start()
{
target.snapToSecondHand = true;
target.secondAttachTransform = GameObject.Find("TwoHandPoint").transform;
}
Scene Anchor Creator (AR Foundation)
Component: ARAnchorManager
public void Start()
{
var sessionOrigin = GameObject.FindObjectOfType<UnityEngine.XR.ARFoundation.ARSessionOrigin>();
var hitPose = new Pose(Vector3.zero, Quaternion.identity); // Replace with hit from ARRaycast
target.AddAnchor(hitPose);
}
### Real-Time Gaze Interaction
Component: Camera
(in VR rig)
public void Update(float deltaTime)
{
var forward = target.transform.forward;
if (Physics.Raycast(target.transform.position, forward, out var hit, 10f))
{
Debug.Log("Looking at: " + hit.collider.name);
}
}
Bind to Input Actions (XR Input Toolkit)
public void Update(float deltaTime)
{
if (UnityEngine.InputSystem.XR.XRController.leftHand.selectInteractionState.activatedThisFrame)
{
Debug.Log("Left trigger pressed");
}
}
🔸 Requires Unity Input System and proper XRController bindings.