You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Meta Quest上访问Unity应用的MIDI数据文件?

Meta Quest上Unity读取StreamingAssets中MIDI文件失败的解决方案

你的问题核心是路径处理错误和Android平台下StreamingAssets的访问逻辑偏差,权限问题并非关键原因(StreamingAssets属于APK内部资源,不需要外部存储权限)。以下是具体问题分析和修复方案:

核心问题拆解

  1. 路径拼接错误:Android平台下Application.streamingAssetsPath的格式为jar:file:///data/app/.../base.apk!/assets,你用Path.Combine拼接路径时会生成带Windows风格反斜杠的URL,导致UnityWebRequest无法识别。
  2. 无法枚举StreamingAssets文件夹:Android打包后,StreamingAssets是APK压缩包内的资源,直接用UnityWebRequest请求文件夹URL不会返回文件列表,这和Windows/编辑器的文件系统逻辑完全不同。
  3. 冗余权限请求:你请求的ExternalStorageRead权限完全没必要,反而会干扰问题排查方向。

修复方案

方案1:预生成文件列表(推荐)

在编辑器中生成包含所有MIDI文件路径的JSON文件,打包时放入StreamingAssets,运行时读取这个JSON获取文件列表,避免在Android下枚举文件夹。

第一步:编辑器脚本生成文件列表

在Editor文件夹下创建脚本:

using System.IO;
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Text.Json;

public class MidiListGenerator : EditorWindow
{
    [MenuItem("Tools/Generate MIDI File List")]
    public static void GenerateMidiList()
    {
        string midiRoot = Path.Combine(Application.streamingAssetsPath, "MidiFiles");
        List<string> midiPaths = new List<string>();

        // 遍历Piano和Drums文件夹
        string pianoFolder = Path.Combine(midiRoot, "Piano");
        if (Directory.Exists(pianoFolder))
        {
            foreach (string file in Directory.GetFiles(pianoFolder, "*.mid"))
            {
                midiPaths.Add($"Piano/{Path.GetFileName(file)}");
            }
        }

        string drumsFolder = Path.Combine(midiRoot, "Drums");
        if (Directory.Exists(drumsFolder))
        {
            foreach (string file in Directory.GetFiles(drumsFolder, "*.mid"))
            {
                midiPaths.Add($"Drums/{Path.GetFileName(file)}");
            }
        }

        // 写入JSON文件
        string jsonPath = Path.Combine(midiRoot, "MidiFileList.json");
        string json = JsonSerializer.Serialize(midiPaths);
        File.WriteAllText(jsonPath, json);
        AssetDatabase.Refresh();
        Debug.Log("MIDI文件列表已生成:" + jsonPath);
    }
}

点击顶部菜单Tools/Generate MIDI File List生成JSON文件。

第二步:修改MidiFileLoader的加载逻辑

替换原有的LoadMidiFiles和LoadMidiFilesFromFolder方法:

// 替换原LoadMidiFiles方法
private IEnumerator LoadMidiFiles()
{
    string listPath = Path.Combine(Application.streamingAssetsPath, "MidiFiles/MidiFileList.json");
    string jsonContent = "";

    if (Application.platform == RuntimePlatform.Android)
    {
        UnityWebRequest request = UnityWebRequest.Get(listPath);
        yield return request.SendWebRequest();
        if (request.result != UnityWebRequest.Result.Success)
        {
            Debug.LogError("读取文件列表失败:" + request.error);
            yield break;
        }
        jsonContent = request.downloadHandler.text;
    }
    else
    {
        jsonContent = File.ReadAllText(listPath);
    }

    List<string> allMidiPaths = JsonSerializer.Deserialize<List<string>>(jsonContent);
    // 根据isDrums筛选路径
    string targetFolder = MidiReader.instance.isDrums ? "Drums/" : "Piano/";
    midiFilePaths = allMidiPaths.Where(p => p.StartsWith(targetFolder)).ToList();

    PopulateMenu();
}

// 移除原LoadMidiFilesFromFolder方法

方案2:修正MIDI文件读取逻辑

确保MidiReader.StartReading方法在Android下用UnityWebRequest读取文件内容,而非File类:

// MidiReader中的StartReading方法示例
public void StartReading(string relativePath)
{
    string fullPath = Path.Combine(Application.streamingAssetsPath, relativePath);
    StartCoroutine(ReadMidiFile(fullPath));
}

private IEnumerator ReadMidiFile(string path)
{
    byte[] midiData = null;

    if (Application.platform == RuntimePlatform.Android)
    {
        UnityWebRequest request = UnityWebRequest.Get(path);
        yield return request.SendWebRequest();
        if (request.result != UnityWebRequest.Result.Success)
        {
            Debug.LogError("读取MIDI文件失败:" + request.error);
            yield break;
        }
        midiData = request.downloadHandler.data;
    }
    else
    {
        midiData = File.ReadAllBytes(path);
    }

    // 解析midiData生成关卡...
}

最后:移除冗余权限请求

删除Start方法中的权限请求代码以及RequestStoragePermissions方法,因为完全不需要。

内容的提问来源于stack exchange,提问作者Omar Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 14:40:54