Help us understand the problem. What is going on with this article?

Oculus Quest Build 7.0アップデート後に自作アプリがおかしくなった時の対策

はじめに

先日Oculus Questがアップデートされて以下の記事のようにコントローラーのトラッキング改善やガーディアンの機能強化されました。

このアップデートで自作したVRアプリを実行するとコントローラーが片手しかトラッキングされなくなったりボタンのマッピングがおかしくなってしまうので対策します。

また、Build 9.0にアップデートされると開発者モードがオフになってしまいます。スマホのアプリから再度オンにしてください。

※追記1
Oculus Integration v1.39.0のOvrAvatarの挙動も変わっているので対策します。
以下のシーンはOvrAvatarが使われていて未対策だとアプリがクラッシュするので対策必須です。

/Assets/Oculus/SampleFramework/Usage/AvatarGrab.scene

※追記2
Build 16.0からAndroidManifest.xml<application>タグにandroid:label="@string/app_name"とリソースファイルのapp_nameの定義、もしくはandroid:label="アプリ名"がないと提供元不明なアプリに表示されなくなりました。Unityが生成するAndroidManifest.xmlは大丈夫なので手動で削除していない限り問題ありません。
また、インストール済みのアプリが見えない場合は再インストールすると見えるようになります。

環境

Unity

コントローラーの対策

公式ドキュメントに設定手順が追加されていました。

v1.41.0からOVRManagerコンポーネントのTarget DeivcesはQuestがデフォルトになったので何も変更しなくてもよくなりました。そのため逆にOculus Goアプリを作る場合は変更が必要となります。

v1.40.0からOVRManagerコンポーネントのTarget Devicesの先頭をQuestに変更するだけでよくなりました。
image.png

v1.39.0とv1.38.0はOVRManagerコンポーネントのTarget Devicesの先頭をQuestに変更した上でAndroidManifest.xmlにuses-featureを追加します。
image.png


公式ドキュメントに追加される前にFix for sideloaded/homebrew apps and games with the new firmware updateで対策を見付けた方がいてAndroidManifest.xml に以下のfeatureを追加すれば両手のコントローラーが正しくトラッキングされます。これはQuestアプリをOculus Storeに提出する時に必須の設定のようです。

AndroidManifest.xml
<uses-feature android:name="android.hardware.vr.headtracking" android:required="true" android:version="1"/>

具体的に以下のいずれかの方法でAndroidManifest.xmlを修正します。

v14.0(v1.46.0)以降

Oculus Integration v14.0(1.46.0)からOVRManagerTarget Devicesがドロップダウンリストからチェックボックスに変わりました。

image.png

v1.40.0以降

Oculus Integration v1.40.0から少し手間が減ったので更新をおすすめします。
v1.38.0とv1.39.0のQuest対応が中途半端なのが混乱の元凶だったんだ…

  1. OVRManagerのTarget DevicesにQuestを追加します。Quest向けアプリなら既に設定済みだと思います。更にv1.41.0はデフォルト値がQuestに変わったので設定不要になりました。逆にOculus Goアプリを作る時に設定変更が必要です。 image.png
  2. Unity2018.4以下でBuild SettingsのビルドシステムがInternalならGradleに変更します。Unity2019.1以上はビルドシステムの項目がなくなりGradleのみになったので特に設定するものはありません。 image.png

以上の設定で独自に/Assets/Plugins/Android/AndroidManifest.xmlがなくてもビルド時にQuestに必要なfeatureが自動で追加されます。

v1.39.0以前

Create store-compatible AndroidManifest.xml

Oculus Store提出用のAndroidManifest.xmlを作る方法です。

  1. v1.40.0以上に更新する方法と同様にOVRManagerのTarget DevicesにQuestを追加します。
  2. 次に/Assets/Plugins/Android/AndroidManifest.xmlを削除します。メニューのOculus > Tools > Remove AndroidManifest.xmlが簡単です。
  3. 最後にメニューのOculus > Tools > Create store-compatible AndroidManifest.xmlを実行します。これで上記のfeatureが含まれたAndroidManifest.xmlが生成されます。あらかじめOVRManagerのTarget DevicesにQuestを入れておかないと必要なfeatureが含まれないので注意してください。 image.png

ビルドして実行エラー対策

  • v1.39.0までのバージョンで生成したAndroidManifest.xmlで「ビルドして実行」を行うと以下のエラーが出ます。これはビルドとインストールまで完了しているのですがUnityから実行する時に必要なandroid.intent.category.LAUNCHERが定義されていないためです。
  • v1.40.0からandroid.intent.category.LAUNCHERが定義されたAndroidManifest.xmlが生成されるようになったのでビルドして実行エラーは出なくなりました。

image.png

そこで以下のようにandroid.intent.category.LAUNCHERを追加するとビルドして実行からアプリの実行までできるようになります。

AndroidManifest.xml
<intent-filter>
    <action android:name="android.intent.action.MAIN"/>
    <category android:name="android.intent.category.INFO"/>
    <category android:name="android.intent.category.LAUNCHER"/> <!-- この行を追加する -->
</intent-filter>

直接記述する

UnityプロジェクトでAndroid向けにビルドすると[Project Folder]/Temp/gradleOut/src/main/AndroidManifext.xmlが生成されるので[Project Folder]/Assets/Plugins/Android/AndroidManifest.xmlにコピーして他のuses-featureの近くに上記のfeatureを追記します。

コールバックで対策する

UnityはGradleプロジェクト生成後に呼ばれるコールバックがあるので以下のスクリプトでAndroidManifest.xmlに上記のfeatureを追加します。

このコールバックを利用すると次のような事もできます。

/Assets/Editor/ModifyUnityAndroidAppManifest.cs
#if UNITY_ANDROID
using System;
using System.IO;
using System.Text;
using System.Xml;
using UnityEditor;
using UnityEditor.Android;

public class ModifyUnityAndroidAppManifest : IPostGenerateGradleAndroidProject
{
    public void OnPostGenerateGradleAndroidProject(string basePath)
    {
        var isVr = PlayerSettings.GetVirtualRealitySupported(BuildTargetGroup.Android);
        var vrSdks = PlayerSettings.GetVirtualRealitySDKs(BuildTargetGroup.Android);
        var hasOculus = Array.Exists(vrSdks, s => s == OVRManager.OCULUS_UNITY_NAME_STR);

        if (isVr && hasOculus)
        {
            if (OVRDeviceSelector.isTargetDeviceQuest)
            {
                var androidManifest = new AndroidManifest(GetManifestPath(basePath));
                androidManifest.EnableQuestApp();
                androidManifest.Save();
            }
        }

    }

    public int callbackOrder => 10;

    private string _manifestFilePath;

    private string GetManifestPath(string basePath)
    {
        if (string.IsNullOrEmpty(_manifestFilePath))
        {
            var pathBuilder = new StringBuilder(basePath);
            pathBuilder.Append(Path.DirectorySeparatorChar).Append("src");
            pathBuilder.Append(Path.DirectorySeparatorChar).Append("main");
            pathBuilder.Append(Path.DirectorySeparatorChar).Append("AndroidManifest.xml");
            _manifestFilePath = pathBuilder.ToString();
        }

        return _manifestFilePath;
    }
}


internal class AndroidXmlDocument : XmlDocument
{
    private string m_Path;
    protected XmlNamespaceManager nsMgr;
    public readonly string AndroidXmlNamespace = "http://schemas.android.com/apk/res/android";
    public readonly string ToolsXmlNamespace = "http://schemas.android.com/tools";

    public AndroidXmlDocument(string path)
    {
        m_Path = path;
        using (var reader = new XmlTextReader(m_Path))
        {
            reader.Read();
            Load(reader);
        }

        nsMgr = new XmlNamespaceManager(NameTable);
        nsMgr.AddNamespace("android", AndroidXmlNamespace);
    }

    public string Save()
    {
        return SaveAs(m_Path);
    }

    public string SaveAs(string path)
    {
        using (var writer = new XmlTextWriter(path, new UTF8Encoding(false)))
        {
            writer.Formatting = Formatting.Indented;
            Save(writer);
        }

        return path;
    }
}

internal class AndroidManifest : AndroidXmlDocument
{
    private readonly XmlElement ApplicationElement;

    public AndroidManifest(string path) : base(path)
    {
        ApplicationElement = SelectSingleNode("/manifest/application") as XmlElement;
    }

    private XmlAttribute CreateAndroidAttribute(string key, string value)
    {
        var attr = CreateAttribute("android", key, AndroidXmlNamespace);
        attr.Value = value;
        return attr;
    }

    private XmlAttribute CreateToolsAttribute(string key, string value)
    {
        var attr = CreateAttribute("tools", key, ToolsXmlNamespace);
        attr.Value = value;
        return attr;
    }

    public void EnableQuestApp()
    {
        const string headTrackingName = "android.hardware.vr.headtracking";
        var headTrackingData = SelectNodes($"/manifest/uses-feature[@android:name='{headTrackingName}']", nsMgr);
        if (headTrackingData != null && headTrackingData.Count > 0)
        {
            return;
        }

        var manifest = SelectSingleNode("/manifest");
        if (manifest == null)
        {
            return;
        }

        // /manifest に <uses-feature android:name="android.hardware.vr.headtracking" android:required="true" android:version="1" tools:node="merge" /> を追加する
        var newUsesFeature = CreateElement("uses-feature");
        newUsesFeature.Attributes.Append(CreateAndroidAttribute("name", headTrackingName));
        newUsesFeature.Attributes.Append(CreateAndroidAttribute("required", "true"));
        newUsesFeature.Attributes.Append(CreateAndroidAttribute("version", "1"));
        newUsesFeature.Attributes.Append(CreateToolsAttribute("node", "merge"));

        manifest.AppendChild(newUsesFeature);
    }
}
#endif

OvrAvatarの対策

  • v1.38.0のOvrAvatarはARMv7向けライブラリしかありません。IL2CPP/ARM64でビルドおよび実行できるのですが手が表示されません。ARMv7でビルドしましょう。
  • v1.39.0以降のOvrAvatarはOculus > Avatars > Edit Settingsから生成したOvrAvatarSettings.assetにId設定が必須になりました。未設定だとクラッシュしてしまうので自分のIdやTesting Your Integrationに用意されているテスト用Idを設定します。 また、ARM64向けライブラリが追加されたのですがIL2CPP/ARM64でビルドして実行するとスプラッシュ画面の後にOculus Questで「アップデート中」が出た場合の対処法と同じダイアログが出て結局実行できません…
  • v1.40.0でARM64でビルドしても動くようになりました。

image.png

またv1.39.0以降のOvrAvatarでController Shaderが追加されていますが/Assets/Oculus/SampleFramework/Usage/AvatarGrab.sceneでは設定されていないのが原因でアバターのオブジェクトを無限生成して落ちてしまいます。
/Assets/Oculus/Avatar/Content/Prefabs/LocalAvatar.prefabを参考にOvrAvatar/AvatarPBRV2Simpleを設定すればよいでしょう。

image.png

セキュリティ設定

Oculus Integration v1.41.0からOVRManagerにセキュリティ設定が追加されました。

  • Disable BackupsをチェックするとAndroidManifest.xmlにandroid:allowBackup="false"が設定されてadbコマンドでもバックアップできなくなります。
  • Enable NSC Configurationをチェックするとネットワークセキュリティ構成が有効になりHTTPS通信が必須になります。設定ファイルは/Assets/Oculus/VR/Editor/network_sec_config.xmlにあるので必要に応じて設定を追加します。

image.png

Low Overhead ModeとOVROverlay

Oculus Integration v1.41.0Unity2018.4.9f1 / Unity2019.2.0f1からLow Overhead Modeが追加されています。このオプションを有効にするとOpenGL ESのエラーチェックをスキップしてパフォーマンスを向上させるのですがOVROverlayを一緒に使うとクラッシュしてしまいます。他にもクラッシュする原因があるかもしれないので安易に有効にするのは危険です。

image.png

OVRVoiceModが同梱されなくなった

Oculus Integration v1.41.0までOVRVoiceMod(ボイスチェンジャーみたいなもの)が同梱されていたのですがv1.42.0から削除されました。
必要な場合は別途ダウンロードすると引き続き利用できます。

GearVRサポート廃止

Oculus開発ブログよりOculus Integration v1.42.0 (Mobile SDK 1.27.0)からGearVRのサポートが廃止されます。GearVRアプリを開発する場合はそれより前のバージョンを使う必要があります。

ハンドトラッキング設定

Oculus Integration v12.0(1.44.0)からOVRManagerにハンドトラッキング設定が追加されました。
デフォルトではControllers Onlyなのでハンドトラッキングを使う場合はControllers And HandsHands Onlyに変更してください。
この設定によりAndroidManifest.xmlに以下が追加されます。

  • Controllers Only
    • 変更なし
  • Controllers And Hands

    AndroidManifest.xml
    <uses-permission android:name="oculus.permission.handtracking" />
    <uses-feature android:name="oculus.software.handtracking" android:required="false" />
    
  • Hands Only

    AndroidManifest.xml
    <uses-permission android:name="oculus.permission.handtracking" />
    <uses-feature android:name="oculus.software.handtracking" android:required="true" />
    

image.png

Enable Focus Awareness

Oculus Integration v13.0(1.45.0)からOVRManagerEnabling Focus Awarenessが追加されました。
Oculus QuestのアプリはシステムUIが表示される時はアプリが一時停止するのですがこの機能を有効にするとアプリが動いたままシステムUIがオーバーレイで表示されるようです。

image.png

Unityエディターでハンドトラッキングサポート

Oculus Integration v13.0(1.45.0)からOculus QuestでOculus Linkを有効にしてUnityエディターをPlayするとハンドトラッキングできます。
ただしマウスやキーボードでUnityエディターをPlayすると動いたのですが、Oculus DesktopからPlayするとUnityエディターが落ちてしまいました。

Unityエディタがクラッシュする件について @torano0314 さんから再現パターンをコメントで教えてきただきました。ハンドトラッキングしたい時はコントローラーが認識されなくなるまで待てば良さそうです。

Oculus Questでハンドトラッキング有効にし、Linkを使ってエディターから実行するとクラッシュする問題ですが、Oculus Desktopには関係なく、コントローラを触っているとクラッシュするみたいです。コントローラが認識されなくなるのを待ち(コントローラが画面から消え、コントローラが必要です、のようなポップアップがでるのを待ち)実行するとクラッシュしないで済みます。
https://forums.oculusvr.com/developer/discussion/86322/v13-15-editor-crashes-on-play-after-upgrading-oculus-integration#latest

また他にもAndroidManifestやOVRManagerのハンドトラッキングの項目に関わらず手とコントローラ両方が有効になっているという問題もあります。(ハンドトラッキングがオフの時は問題ないかもしれません。)

この問題はv13のときにOculusに報告したのですがまだ解決されず、v15でも続いているみたいです。何か解決策がないかと探しているのですが見つからず。。。

dynamic foveation

Oculus Integration v14.0(1.46.0)からOVRManagerにdynamic foveationが追加されました。有効にすると適切なfoveation levelに設定されます。

/// <summary>
/// Let the system decide the best foveation level adaptively (Off .. fixedFoveatedRenderingLevel)
/// This feature is only supported on QCOMM-based Android devices
/// </summary>
public static bool useDynamicFixedFoveatedRendering
{
    get
    {
        if (!OVRPlugin.fixedFoveatedRenderingSupported)
        {
            Debug.LogWarning("Fixed Foveated Rendering feature is not supported");
        }
        return OVRPlugin.useDynamicFixedFoveatedRendering;
    }
    set
    {
        if (!OVRPlugin.fixedFoveatedRenderingSupported)
        {
            Debug.LogWarning("Fixed Foveated Rendering feature is not supported");
        }
        OVRPlugin.useDynamicFixedFoveatedRendering = value;
    }
}

Color Gamut

Oculus Integration v14.0(1.46.0)からOVRManagerColor Gamutを設定できるようになりました。

color_gamut.png

OVRVignette

Oculus Integration v15.0(1.47.0)からOVRVignetteが追加されてCameraと同じGameObjectにアタッチするとVignetteエフェクトを表現できます。

image.png

XR Managementパッケージ利用時の注意

Package ManagerにあるXR ManagementとXR SettingsのVRサポートはどちらか一方しか利用できません。またXR Managementパッケージを利用する時はOculus XR Pluginも一緒に利用しないとOVRInputなどが動作しなくなるので必ずOculus Loaderを設定してInitialize on Startupを有効にしてください。

image.png

Oculus Integration更新時に注意すること

Oculus Integrationはバージョンアップでファイルのパスが変わることがあるので上書き更新するとおかしな状態になる事があります。そのため/Assets/Oculus//Assets/Oculus.metaを削除した後に新規でインポートすることをお勧めします。その際にUnityから/Assets/Oculus/を削除してもUnityがdllをロックしているのでいくつか削除されないファイルがあります。
なので以下の手順が確実です。

  1. 一旦、Unityを終了する
  2. エクスプローラから/Assets/Oculus//Assets/Oculus.metaを削除する
  3. Unityを開く。この時Oculus Integrationがないのでエラーが出るが一旦無視する
  4. Asset StoreからOculus Integrationをインポートする

Oculus Link

Oculus HomeおよびOculus Quest v13から「コントロールパネル > サウンド > 再生」にあるOculus Virtual Audio Deviceの名前をHeadphonesにしないとOculus Linkにつながらなくなりました。

https://forums.oculusvr.com/community/discussion/comment/730475/#Comment_730475

UE4

コントローラーの対策

公式ドキュメントに設定手順が追加されていました。

image.png


UE4.23以降

  1. プロジェクト設定 > Oculus VRプラグインのLaunch Oculus Performance WindowsからTarget PlatformMobileに変更します。
  2. プロジェクト設定 > Android > Advanced APK PackagingのPackage for Oculus Mobile devicesOculus Questを追加します。

以上を設定することでEngine\Plugins\Runtime\Oculus\OculusVR\Source\OculusHMD\OculusMobile_APL.xmlによりAndroidManifest.xmlにfeatureが追加されます。

image.png

image.png

UE4.22以前

[Project Folder]/Build/Android/ManifestRequirementsAdditions.txtに上述したfeatureを記述するとビルド時にAndroidManifest.xmlに追加されます。このフォルダはプロジェクト設定のビルドフォルダを開くボタンから開くことができます。
以下のリンクではManifestRequirementsOverride.txtが使われていますがUE4独自の設定も上書きするので追加だけのManifestRequirementsAdditions.txtの方が安全です。

image.png

ハンドトラッキングの対策

UE4.24以前

Oculus Unreal Integrationならハンドトラッキングに対応したMobile SDKが入っていますが設定画面やBlueprintなどがありません。
ハンドトラッキングAPIはC++から呼び出し、上記のManifestRequirementsAdditions.txtにハンドトラッキング用のuses-permissionuses-featureを記述すると動作します。

原因

今後Oculus QuestにはOculus Goをエミュレートする機能が追加される予定です。その機能が一部取り込まれて今回のfeatureがあるとQuest向け、ないとGo向けとして動作しているのではないかと思われます。

参考リンク

kadinche
弊社では 2008年の会社設立当初から、一貫して VR ソリューションの研究開発に取り組んでいます。
https://www.kadinche.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした