Skip to content

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 keyword target will dynamically reflect the selected component and give you full access to its members.


Live Haptic Feedback Test

Selected component: XRBaseController

public void Start()
{
    target.SendHapticImpulse(0.7f, 0.2f);
}
Use Case: Instantly test different haptic intensities and durations on VR controllers.

Disable Input Actions Temporarily

Selected component: XRBaseController

public void Start()
{
    target.enableInputActions = false;
}
Use Case: Debug input issues or pause controller behavior without restarting the app.

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);
}
Use Case: Live inspect whether a button is being held — great for input debugging and tutorials.

Instant Grab with No Physics

Selected component: XRGrabInteractable

public void Start()
{
    target.attachEaseInTime = 0f;
    target.throwOnDetach = false;
}
Use Case: Create instant stickiness for UI objects or tools.

Adjust Raycast Behavior

Selected component: XRRayInteractor

public void Update(float dt)
{
    target.maxRaycastDistance = 50f;
    target.lineType = UnityEngine.XR.Interaction.Toolkit.XRRayInteractor.LineType.ProjectileCurve;
}
Use Case: Test line rendering types in real-time — swap between laser pointer or arc.

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);
}
Use Case: Add real-time visual feedback or cue for rotation.

Highlight Reticle Switching

Selected component: XRInteractorLineVisual

public void Start()
{
    target.reticle = GameObject.Find("CustomReticle");
    target.lineWidth = 0.015f;
}
Use Case: Change visuals of gaze-based interactions based on game state or user role.

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
}
Use Case: See exactly where the HMD is looking — helpful for UI placement or comfort testing.

Lock Grabbed Object

Selected component: XRGrabInteractable

public void Start()
{
    target.movementType = UnityEngine.XR.Interaction.Toolkit.XRBaseInteractable.MovementType.Kinematic;
}
Use Case: Prevent object from being thrown or moved — good for fixed tools or anchored systems.

XR Ray Interactor Debug Visual

Component: XRRayInteractor

public void Start()
{
    target.lineType = UnityEngine.XR.Interaction.Toolkit.XRRayInteractor.LineType.ProjectileCurve;
    target.maxRaycastDistance = 10f;
}
Use Case: Instantly switch and preview different raycasting line types (Straight, Bezier, Projectile) without modifying inspector settings. Great for tuning visuals during testing or level design.

Real-Time Interactor Layer Tuner

Component: XRRayInteractor

public void Start()
{
    target.raycastMask = LayerMask.GetMask("UI", "Interactables");
}
Use Case: Dynamically update which layers your ray interacts with. This allows you to test interactions across different sets of objects (e.g., toggling UI-only mode).

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;
}
Use Case: Tune physical object pickup & throw feel live while playing. Helps perfect the “weight” of VR objects without recompilation.

Instant Grabbable Lock

Component: XRGrabInteractable

public void Start()
{
    target.interactionLayerMask = LayerMask.GetMask("Nothing");
}
Use Case: Disable grabbing behavior at runtime for debugging or tutorial purposes, without touching prefabs or inspector.

One-Hand or Two-Hand Toggle

Component: Custom Component with XRGrabInteractableTwoAttach

public void Start()
{
    target.snapToSecondHand = true;
    target.secondAttachTransform = GameObject.Find("TwoHandPoint").transform;
}
Use Case: Dynamically enable two-hand grab interactions by referencing runtime transforms. Useful for weapon systems or tools in VR.

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);
}
Use Case: Programmatically add anchors to test placement logic and session persistence. Helps simulate AR object pinning.

### 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);
    }
}
Use Case: Simulate gaze-based interaction before building full VR UI systems.

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");
    }
}
**Use Case: Check input activation in real time.

🔸 Requires Unity Input System and proper XRController bindings.