公司动态
Unity StreamingAssets完全指南
一、基本概念StreamingAssets是 Unity 中一个特殊的文件夹,位于Assets/StreamingAssets/。它的核心特点是:打包时原样复制到最终应用中,不做任何压缩、加密或格式转换,可通过文件路径直接访问。二、核心特性特性说明原样保留文件不会被 Unity 处理,保持原始格式只读运行时只能读,不能写平台差异不同平台访问方式不同(尤其是 Android)不参与打包压缩会增加安装包体积无引用检测Unity 不会追踪其中资源的引用关系三、各平台路径Unity 提供Application.streamingAssetsPath获取该目录路径:平台实际路径Editor / Standalone(PC/Mac)项目路径/Assets/StreamingAssets或exe_Data/StreamingAssetsiOSApplication/Data/RawAndroidjar:file:///data/app/xxx.apk!/assets/⚠️ 在 APK 内部WebGLURL/StreamingAssets四、读取方式1. PC / iOS / Editor(可直接用 File API)stringpathPath.Combine(Application.streamingAssetsPath,config.json);stringcontentFile.ReadAllText(path);2. Android(必须用 UnityWebRequest)⚠️Android 上的 StreamingAssets 位于 APK 压缩包内,无法用 File API 直接读取,必须使用UnityWebRequest:IEnumeratorLoadFromStreamingAssets(stringfileName){stringpathPath.Combine(Application.streamingAssetsPath,fileName);#ifUNITY_ANDROID !UNITY_EDITOR// Android 必须用 UnityWebRequest#elsepathfile://path;#endifUnityWebRequestrequestUnityWebRequest.Get(path);yieldreturnrequest.SendWebRequest();if(request.resultUnityWebRequest.Result.Success){stringcontentrequest.downloadHandler.text;Debug.Log(content);}}3. 统一封装(推荐)publicstaticclassStreamingAssetsReader{publicstaticIEnumeratorReadText(stringrelativePath,ActionstringonComplete){stringpathPath.Combine(Application.streamingAssetsPath,relativePath);#if!UNITY_ANDROID || UNITY_EDITORpathfile://path;#endifusing(UnityWebRequestreqUnityWebRequest.Get(path)){yieldreturnreq.SendWebRequest();if(req.resultUnityWebRequest.Result.Success)onComplete?.Invoke(req.downloadHandler.text);elseDebug.LogError($读取失败:{req.error});}}publicstaticIEnumeratorReadBytes(stringrelativePath,Actionbyte[]onComplete){stringpathPath.Combine(Application.streamingAssetsPath,relativePath);#if!UNITY_ANDROID || UNITY_EDITORpathfile://path;#endifusing(UnityWebRequestreqUnityWebRequest.Get(path)){yieldreturnreq.SendWebRequest();if(req.resultUnityWebRequest.Result.Success)onComplete?.Invoke(req.downloadHandler.data);}}}五、典型应用场景✅ 适合放的内容游戏初始配置文件(JSON、XML、CSV)首包 AssetBundle(热更新前的初始资源)视频文件(播放前不需要处理)数据库文件(如 SQLite 的.db,需先复制到可写目录)第三方 SDK 配置文件❌ 不适合放的内容需要频繁修改的数据(该目录只读)Unity 需要识别的资源(如 prefab、材质等,应放 Assets 或 Resources)敏感数据(明文可被解压查看)六、StreamingAssets vs 其他目录对比对比项StreamingAssetsResourcespersistentDataPath读写只读只读✅ 可读写是否打包✅ 打入包体✅ 打入包体❌ 运行时生成是否压缩❌ 原样保留✅ Unity 处理-访问方式文件路径Resources.Load文件路径Android 特殊✅ 需 WebRequest无无特殊典型用途首包 AB、配置少量常驻资源存档、热更资源七、常见使用模式:首次启动复制到可写目录由于 StreamingAssets只读,常见做法是首次启动时复制到persistentDataPath,之后从可写目录读取和更新:IEnumeratorCopyToPersistent(stringfileName){stringsrcPathPath.Combine(Application.streamingAssetsPath,fileName);stringdstPathPath.Combine(Application.persistentDataPath,fileName);if(File.Exists(dstPath))yieldbreak;// 已复制过#if!UNITY_ANDROID || UNITY_EDITORsrcPathfile://srcPath;#endifusing(UnityWebRequestreqUnityWebRequest.Get(srcPath)){yieldreturnreq.SendWebRequest();if(req.resultUnityWebRequest.Result.Success){File.WriteAllBytes(dstPath,req.downloadHandler.data);Debug.Log($复制完成:{dstPath});}}}八、热更新架构中的典型作用安装包首次启动: ┌─────────────────────┐ ┌──────────────────────┐ │ StreamingAssets │──复制→│ persistentDataPath │ │ (首包 AB 版本号) │ │ (可写,支持更新) │ └─────────────────────┘ └──────────────────────┘ │ ↓ 远程 CDN 下载新版本 AB 覆盖 persistentDataPath加载顺序:优先从persistentDataPath读取(热更后的资源),若无则回退到StreamingAssets(首包资源)。stringGetABPath(stringabName){stringpersistentPathPath.Combine(Application.persistentDataPath,abName);if(File.Exists(persistentPath))returnpersistentPath;// 热更资源优先returnPath.Combine(Application.streamingAssetsPath,abName);// 首包资源兜底}九、注意事项 ⚠️Android 不能用 File.Exists 判断:APK 内文件用File.Exists会返回 false,需用UnityWebRequest尝试请求。路径不要用反斜杠:统一用Path.Combine或/。大文件谨慎放:直接影响安装包大小。Meta 文件不打包:.meta文件不会随资源打入包体。子目录支持:可以任意建子目录,路径需一致。iOS 大小写敏感:注意文件名大小写。十、常见问题 FAQQ1: 为什么 Android 上 File.ReadAllText 读不到?A: APK 是压缩包,文件不在真实文件系统中,必须用 UnityWebRequest。Q2: StreamingAssets 里的文件会被压缩加密吗?A: 不会,原样保留,容易被解包查看,不要放敏感内容。Q3: 可以运行时写入吗?A: 不能,请写入Application.persistentDataPath。Q4: StreamingAssets 会打入 Resources 索引吗?A: 不会,Unity 不会识别里面的资源。