【VR・VRChat】VIVE Focus Vision トラブルシューティング書きなぐり

共通環境

・OS: Windows 11 24H2

・CPU: Intel Core i5-12600KF

・RAM: 32GB

GPU: RTX 4060

・無線ルーター: NEC PA-WX11000T12 (5 Ghz) / NEC Aterm WG1400HP (5 Ghz)

Ultimate TrackerをFocus Visionにペアリングしてワイヤレスストリーミングをプレイ中、読み込み画面や映像 / 音声の途切れ(スタッタリング)が頻繁に発生する

 環境

・Vive Hub: 2.3.3b

  - VIVEストリーミング: 2.2.4

・Focus Vision: 7.0.999.326

・Ultimate Tracker: 1.0.999.169

 対策(追記:2025/08/16)

・ストリーミングに使用する無線ルーターNEC PA-WX11000T12からNEC Aterm WG1400HPに変更したところ、現象が発生しなくなった

 対策(旧)

※Focus Vision FW 7.0.999.344にて、下記手順で改善しなくなった

・Vive Hubにて下記設定を行う(グレーアウトは恐らく影響のない項目)

  - "パフォーマンス"タブ

    - "ビットレート" > "120 Mbps"(私の環境では200 Mbpsを設定すると、稀にスタッタリングが発生した)

    - "ダイナミックビットレート" > "オフ"

    - "送信モード" > "TCP"

  - "グラフィックス"タブ

    - "ストリーミンググラフィックスの設定" > "自動"

    - "FPS" > "90 fps"

    - "鮮明化" > "+6"

    - "パススルーMR" > "オフ"

・Ultimate Trackerを接続後に、"設定" > "接続設定" > "Wi-Fi"から別のアクセスポイントへ切り替え、元のアクセスポイントへ戻してワイヤレスストリーミングを開始または再開する

・無線ルーターQoS設定でFocus VisionのPriorityを上げる

 備考(旧)

私の環境では、ワイヤレスストリーミング開始前に上記Wi-Fiのアクセスポイントの切り替え、再接続(同ルーターの5 GHz - 6 Ghz間)の手順を挟むことでストリーミング中の通信が安定した

Focus Vision本体にUltimate Trackerをペアリング時、ワイヤレスストリーミングをプレイ中にバッテリーのホットスワップを行うと、レジューム後接続していたUltimate Tracker複数台(1~2台)が再接続できなくなる(ことがある)

 復帰手段(追記:2025/08/16)

Ultimate Trackerドングルの抜去による再接続を行う

 復帰手段(旧)

Ultimate Trackerの再ペアリングを行う

VIVE Focus Visionコントローラーのサムスティックのタッチセンサーの感度が悪く、VRChatにおいてピースサイン等の親指を使用するジェスチャー操作が行いづらい

コントローラーのサムレスト("/input/parking"の"タッチ")に"gesture_activator_thmb"をバインドする

境界(プレイエリア)がナナメに傾いている

・本体を初期化する

・Focus Vision本体前面のカメラ部分をタオル等で隠した状態で、"設定" > "境界"から"視界" / "フロアの位置" / "安全境界"のいずれかをリセットする(?)

> my floor is tilted on the focus vision, how do i fix that?

> the only way I know of fixing it is by throwing a sheet or something over your headset while you have it on to block the cameras, to trick it into resetting your boundaries/setup

https://discordapp.com/channels/946305475467706419/962856801555054613/1340811836672577566 (Discord VIVE公式コミュニティサーバー)

6個以上のUltimate Trackerを同時に使用する

Focus VisionまたはXR EliteとPCそれぞれにドングルを接続することで、Vive Space Calibratorを用いてFocus Vision (5) + PC (3)のように、6個以上のUltimate Trackerを同時に使用できる(らしい)

> can i use the xr elite + 6 ultimate trackers with pcvr?
> you can use 5 trackers connected directly to the xr elite and 1 to the pc

https://discordapp.com/channels/946305475467706419/1180030550476603493/1303291747165671426 (Discord VIVE公式コミュニティサーバー)

Focus Vision本体からUltimate Trackerのファームウェアをアップデートを行った際、プログレスが40%で止まり進行しなくなる

 復帰手段(※保証はしません)

Ultimate Tracker FW 1.0.999.168 から、 1.0.999.169へのアップデートで発生

約1時間待機しても進行しなかった

ヘッドセットボタン長押しから本体の強制シャットダウンを行い、PCのVive HubからFWをアップデートすることができた

Ultimate TrackerのFWアップデートはVive Hubから行ったほうが無難そう

VIVE Focusシリーズ用バッテリーが、VIVE公式ストアで販売していない

リチウムイオンバッテリーのため、安全上の観点でVIVE公式ストア(台湾)から販売ができないとのこと

ビックカメラソフマップ、コジマネットで販売している(2025年3月現在)

VIVE Focusシリーズ用コントローラーとVIVE リストトラッカーを同時にペアリングしたい

現状、FW 7.0.999.326ではできない

ストリーミングプレイ中にUltimate Trackerドングルの接続ダイアログが表示される

延長ケーブルもしくはコネクタ部分が断線 / 接触不良を起こしている可能性

私の環境では延長ケーブルの交換で改善された

 

【Unity】任意のAnimation Stateと現在再生されているStateを比較する

はじめに

Animatorのパラメーター/ステートは文字列ではなくハッシュ値で管理するとよい

(例)

protected Animator m_Animator;

//~~~

m_Animator.SetTrigger("Attack");

ではなく

protected Animator m_Animator;

readonly int hashAttack = Animator.StringToHash("Attack");

//~~~

m_Animator.SetTrigger(hashAttack);

の方が好ましい

現在のステートを取得する

AnimatorStateInfo、Animator.GetCurrentAnimatorStateInfoを使用する

docs.unity3d.com

protected AnimatorStateInfo m_CurrentStateInfo;   //現在のハッシュ値が入る
protected Animator m_Animator;

void Awake(){
   m_Animator = GetComponent<Animator>();
}

void Update(){
    m_CurrentStateInfo = m_Animator.GetCurrentAnimatorStateInfo(0);
}

Base Layerのみを使う場合

f:id:sirataki76:20200922203926p:plain

protected AnimatorStateInfo m_CurrentStateInfo;
protected Animator m_Animator;

//State Hash
readonly int hashStateLocomotion = Animator.StringToHash("Locomotion");

void Awake(){
   m_Animator = GetComponent<Animator>();
}

void Update(){
    m_CurrentStateInfo = m_Animator.GetCurrentAnimatorStateInfo(0);    //Base Layerのみの取得なので0を入れる

    Debug.Log(IsStateLocomotion());
}

bool IsStateLocomotion(){
    bool isState = m_CurrentStateInfo.shortNameHash == hashStateLocomotion;

    return isState;
}

 

いくつかのLayerを組み合わせて使う場合

例としてBase Layerの他にAttack、Damage用にの2つのレイヤーを追加したもの(計3つのレイヤー)を使用する

f:id:sirataki76:20200922211520p:plain

複数のレイヤーからStateを比較するときはfullPathHashを使って比較する

protected AnimatorStateInfo[] m_CurrentStateInfo = new AnimatorStateInfo[3];
/*
protected AnimatorStateInfo[] m_NextStateInfo = new AnimatorStateInfo[3];
protected bool[] m_IsAnimatorTransitioning = new bool[3];
*/
protected Animator m_Animator;

//Parameter Hash
readonly int hashAttack = Animator.StringToHash("Attack");

//State Hash
readonly int hashStateLocomotion = Animator.StringToHash("Base Layer.Locomotion");    //Layer名.State名
readonly int hashStateAttack_1 = Animator.StringToHash("Attack.AttackSM.Attack_1");    //Layer名.StateMachine名.State名

void Awake(){
   m_Animator = GetComponent<Animator>();
}

void Update(){
    for(int i = 0; i < 3; ++i){
        m_CurrentStateInfo[i] = m_Animator.GetCurrentAnimatorStateInfo(i);
        /*
        m_NextStateInfo[i] = m_Animator.GetNextAnimatorStateInfo(i);
        m_IsAnimatorTransitioning[i] = m_Animator.IsInTransition(i);
        */
    }
}

bool IsStateLocomotion(){
    bool isState = m_CurrentStateInfo[0].fullPathHash == hashStateLocomotion;

    return isState;
}

bool IsStateAttack(){
    bool isState = m_CurrentStateInfo[1].fullPathHash == hashStateAttack_1;    //AnimatorStateInfo[]のIndexをレイヤーと同じ番号にすること

    return isState;
}

今回はAnimator.GetCurrentAnimatorStateInfoのみを用いたが、他にもAnimator.GetNextAnimatorStateInfoやAnimator.IsInTransitionを使って比較できたりもする

Unity - Scripting API: Animator.StringToHash

Unity - Scripting API: Animator.GetCurrentAnimatorStateInfo

Unity - Scripting API: Animator.GetNextAnimatorStateInfo

Unity - Scripting API: Animator.IsInTransition

【Unity】アクションゲームで使える攻撃判定を作る

やりたいこと

任意の座標・大きさの範囲内にあるコライダーを取得したい

 

結論

Physics.OverlapBoxNonAlloc

Physics.OverlapSphereNonAlloc

Physics.OverlapCapsuleNonAlloc

docs.unity3d.com

 

を使う

 

解説(?)

3Dで攻撃判定を作るときBoxColliderやCapsuleColliderを使う手段もありますが、攻撃判定を一度に複数用意したい・判定の大きさを変えたいとなった際ちょっと不便です

また、Colliderは触れたものすべてをメモリに溜め込むため(Layerである程度ふるいにかけることはできますが)一度の判定で膨大な数のオブジェクトを取得してしまうこともあります

 

対してPhysics.Overlap~NonAllocは個数や大きさ、座標を簡単に変えられたり、決めた要素数以上のオブジェクトを取得しない仕組みになっているため、GCの発生を抑えることができます

 

以下サンプル

 

Get Collider