> ## Documentation Index
> Fetch the complete documentation index at: https://docs-unity.molca.id/llms.txt
> Use this file to discover all available pages before exploring further.

# Controller Visual

> Hand/controller model switching, button rim highlighting, and hand animation input bridge.

**Folder:** `Assets/_MolcaSDK/_VR/Scripts/Controller Visual/`

This layer controls controller presentation and button guidance:

* `VRControllerVisual.cs`
* `VRControllerVisualHelper.cs`
* `HandAnimator.cs`

## VRControllerVisual

**File:** `Assets/_MolcaSDK/_VR/Scripts/Controller Visual/VRControllerVisual.cs`\
**Namespace:** `MolcaSDK.VR`

Main component for each hand/controller visual. It provides:

* appearance mode switch (`handModel` vs `controllerModel`),
* per-button rim toggle (`Grip`, `Trigger`, `Primary`, `Secondary`, `Thumbstick`, `Menu`),
* global rim settings (`rimColor`, `rimPower`, `rimIntensity`, pulse fields),
* button transform lookup (`GetButtonTransform(ButtonType)`),
* input-driven rim update through XRI input readers.

## VRControllerVisualHelper

**File:** `Assets/_MolcaSDK/_VR/Scripts/Controller Visual/VRControllerVisualHelper.cs`

Inspector-friendly helper that drives left/right visuals through UnityEvents and context-menu actions.

It resolves `VRSubsystem` after `RuntimeManager.WaitForInitialization()` and uses:

* `VRPlayerManager.LeftControllerVisual`
* `VRPlayerManager.RightControllerVisual`

to toggle:

* rim state for selected button types,
* all-button rim enable/disable,
* hand mode vs controller mode for each side.

## HandAnimator

**File:** `Assets/_MolcaSDK/_VR/Scripts/Controller Visual/HandAnimator.cs`

Bridges trigger/grip input values into Animator parameters:

* reads `Trigger` and `Grip` from XRI input readers,
* writes blend-tree float params each frame,
* supports `PlayGrabAnimation(stateName)` and `StopGrabAnimation()`,
* crossfades between custom grab state and default blend state.

## Code

Toggle trigger highlight on both controllers from a UnityEvent target:

```csharp theme={null}
using MolcaSDK.VR;
using UnityEngine;

public class ControllerHintTrigger : MonoBehaviour
{
    [SerializeField] private VRControllerVisualHelper visualHelper;

    public void ShowHint() => visualHelper.EnableRimLighting();
    public void HideHint() => visualHelper.DisableRimLighting();
}
```

## Inspector checklist

* Assign all button renderers in `VRControllerVisual` (null refs break per-button effects).
* Ensure materials support the rim shader properties (`_EnableRim`, `_RimColor`, etc.).
* Set left/right button types in `VRControllerVisualHelper` and avoid `None` if you expect output.
* For `HandAnimator`, verify Animator parameter names match controller defaults (`Trigger`, `Grip`) or your custom names.

## Troubleshooting

* **Rim never appears** - renderer/material not assigned or shader lacks rim properties.
* **Helper does nothing** - `VRPlayerManager` controller visual refs missing, or `VRSubsystem` not ready yet.
* **Only one side updates** - left/right button type may be `None` for that side.
* **Hand animation frozen** - check Animator controller assignment and trigger/grip parameter names.

## Related

* [VRPlayerManager](/vr/vr-player-manager)
* [VR step auxiliaries](/vr/steps/vr-step-auxiliaries)
* [VR locomotion](/vr/locomotion)
