Unity构建的Android应用无法在运行时访问SD卡中的Addressables场景包
Unity构建的Android应用无法在运行时访问SD卡中的Addressables场景包
我之前做Unity Android项目时,刚好碰到过几乎一模一样的场景加载问题,结合你用的Android 7(API 25)系统特性,给你梳理几个关键解决步骤,应该能帮你搞定:
1. 先搞定存储权限的问题
Android 7(API 25)属于API 23及以上版本,必须动态申请存储权限,只在Manifest里加权限是不够的:
- 先在Unity的
Project Settings > Player > Publishing Settings > Build里勾选Custom Main Manifest,然后在生成的AndroidManifest.xml中添加这两个权限:<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - 然后在Unity代码里,要么在应用启动时,要么在点击加载按钮前,主动申请权限:
注意:有些定制化ROM(比如MIUI、EMUI)可能需要用户手动在系统设置里给应用开启「存储权限」,哪怕代码里申请了也可能被拦截,测试时可以先去系统设置确认权限是否开启。using UnityEngine; using UnityEngine.Android; public class PermissionHandler : MonoBehaviour { void Start() { if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite)) { Permission.RequestUserPermission(Permission.ExternalStorageWrite); } if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageRead)) { Permission.RequestUserPermission(Permission.ExternalStorageRead); } } }
2. 确认SD卡的真实路径,别用硬编码的固定路径
很多人会踩坑:把SD卡路径硬编码成/storage/sdcard/,但不同厂商的SD卡路径可能不一样(比如/storage/XXXX-XXXX/,XXXX是随机生成的分区ID)。正确的做法是通过Android原生API获取真实的SD卡路径:
public static string GetSDCardPath() { AndroidJavaClass environmentClass = new AndroidJavaClass("android.os.Environment"); AndroidJavaObject externalStorageDirs = environmentClass.CallStatic<AndroidJavaObject>("getExternalFilesDirs", (object)null); AndroidJavaObject[] dirs = externalStorageDirs.Call<AndroidJavaObject[]>("toArray"); // 第一个是内部存储的外部目录,第二个通常是SD卡的目录 if (dirs.Length >= 2) { string sdPath = dirs[1].Call<string>("getAbsolutePath"); // 截取到SD卡根目录(去掉后面的Android/data/包名/files部分) sdPath = sdPath.Substring(0, sdPath.IndexOf("Android/data/")); return sdPath; } // 如果没找到SD卡,返回内部存储路径 return Application.persistentDataPath; }
拿到真实路径后,再拼接你的.bundle文件的相对路径,比如GetSDCardPath() + "/MyBundles/Scene1.bundle",然后用File.Exists()先判断文件是否存在,排除路径错误的问题。
3. 配置Addressables从自定义SD卡路径加载
Addressables默认会从内置的StreamingAssets或者远程服务器加载,要让它从SD卡加载,需要做以下配置:
- 首先,确保你打包Addressables时,对应的Group的「Content Packing & Loading」设置中,「Build Path」和「Load Path」不要用默认的Remote路径,而是留空或者设置为自定义变量。
- 在运行时,手动指定Addressables的加载路径,或者直接加载SD卡上的bundle文件:
另外,也可以通过修改Addressables的Profile,把RemoteLoadPath设置为SD卡的路径变量,这样更符合Addressables的规范。using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using System.IO; public async void LoadSceneFromSDCard() { string bundlePath = GetSDCardPath() + "/MyBundles/Scene1.bundle"; if (!File.Exists(bundlePath)) { Debug.LogError("Bundle文件不存在:" + bundlePath); return; } // 先加载bundle作为外部资源 AsyncOperationHandle<AssetBundle> bundleHandle = Addressables.LoadAssetBundleAsync(bundlePath); await bundleHandle.Task; if (bundleHandle.Status == AsyncOperationStatus.Succeeded) { // 从bundle中加载场景 AsyncOperationHandle<SceneInstance> sceneHandle = Addressables.LoadSceneAsync("Scene1", LoadSceneMode.Additive); await sceneHandle.Task; if (sceneHandle.Status == AsyncOperationStatus.Succeeded) { Debug.Log("场景加载成功!"); } } else { Debug.LogError("加载Bundle失败:" + bundleHandle.OperationException); } }
4. 检查Unity的Player Settings设置
最后确认Unity的打包设置:
- 打开
Project Settings > Player > Android > Other Settings - 把「Write Access」设置为External (SDCard),这样Unity会允许应用访问外部存储
- 确保「Minimum API Level」设置为25,和你的目标设备一致
按照这几个步骤排查下来,基本就能解决SD卡中Addressables场景包加载失败的问题了。
内容来源于stack exchange
相关产品推荐
相关产品推荐

