アドカレ
KENTOのひとりアドカレ11日目の記事です。
https://qiita.com/advent-calendar/2025/kento
環境情報
| ツール/SDK | バージョン |
|---|---|
| Unity | 6000.0.62f1 |
| Meta XR Core SDK | 81.0.0 |
| Open XR Plugin | 1.16.0 |
| XR Interaction Toolkit | 3.0.9 |
| XR Hands | 1.7.1 |
事前準備は以下の通りです。
遠い距離のオブジェクトがつかめない
原因はAimPoseにあります。ハンドトラッキング時のレイの起点となるGameObjectでTrackedPoseDriverによる位置制御が行われています。シミュレーター利用時はこの値が更新されず、レイが正しく飛んでいません。
Near Far Interactorにフォーカスした状態でSceneを見ると、Rayがデバッグ表示されるのですが、以下画像のようにハンドトラッキングに追従していないことが分かります。

InputActionのAimPosition/Rotationがシミュレーターの実行環境では動作しないようになっていると推測します。

解決策
ハンドトラッキングのBone情報からおおよそのAimPoseをシミュレートするコードで代替します。
using UnityEngine;
using UnityEngine.InputSystem.XR;
using UnityEngine.XR.Hands;
/// <summary>
/// AimPose をジョイントデータからシミュレートするクラス。
/// </summary>
[RequireComponent(typeof(TrackedPoseDriver))]
public class SimulatedAimPose : MonoBehaviour
{
[SerializeField] private Handedness _handedness = Handedness.Right;
private TrackedPoseDriver _trackedPoseDriver;
private void Awake()
{
// 実機またはビルド時は削除して何もしない。
if (!Application.isEditor || MetaQuestLinkChecker.IsLink)
{
Destroy(this);
return;
}
_trackedPoseDriver = GetComponent<TrackedPoseDriver>();
_trackedPoseDriver.enabled = false;
}
private void Update()
{
var xrHandSubsystemUtility = XRHandSubsystemUtility.Instance;
if (!xrHandSubsystemUtility.IsSubsystemRunning) return;
var isTracked = _handedness == Handedness.Left
? xrHandSubsystemUtility.IsLeftHandTracked
: xrHandSubsystemUtility.IsRightHandTracked;
if (!isTracked) return;
if (TryGetPinchPosition(xrHandSubsystemUtility, _handedness, out var position))
{
transform.localPosition = position;
}
if (TryGetPalmRotation(xrHandSubsystemUtility, _handedness, out var rotation))
{
transform.localRotation = rotation;
}
}
private bool TryGetPinchPosition(
XRHandSubsystemUtility utility,
Handedness handedness,
out Vector3 position)
{
var subsystem = utility.Subsystem;
var hand = handedness == Handedness.Left ? subsystem.leftHand : subsystem.rightHand;
var thumbTip = hand.GetJoint(XRHandJointID.ThumbTip);
var indexTip = hand.GetJoint(XRHandJointID.IndexTip);
if (!thumbTip.TryGetPose(out var thumbTipPose) || !indexTip.TryGetPose(out var indexTipPose))
{
position = Vector3.zero;
return false;
}
position = Vector3.Lerp(thumbTipPose.position, indexTipPose.position, 0.5f);
return true;
}
private bool TryGetPalmRotation(
XRHandSubsystemUtility utility,
Handedness handedness,
out Quaternion rotation)
{
var subsystem = utility.Subsystem;
var hand = handedness == Handedness.Left ? subsystem.leftHand : subsystem.rightHand;
var palm = hand.GetJoint(XRHandJointID.Palm);
if (!palm.TryGetPose(out var palmPose))
{
rotation = Quaternion.identity;
return false;
}
rotation = palmPose.rotation;
return true;
}
}
各HandのAimPoseにアタッチします。
合わせて、近距離編で行ったつかみ判定のカスタムReaderの実装も必要です。
参考リンク:【Meta Quest】XR Interaction Toolkitのサンプルにおいて、XR Device Simulator利用時にハンドトラッキングのつかむ機能が動かない(近距離編)


