🔍搜索⌘K

Unity 特殊路径全解析:从文件夹规则到多平台适配

概述

在 Unity 开发里,「路径」是连接「资源管理」和「多平台发布」的关键一环。Unity 有一批特殊命名的文件夹(比如 StreamingAssets、Resources、Editor),它们的打包规则、读写权限、访问方式都是固定的;同时,Application 类提供的路径 API(比如 dataPath、persistentDataPath)在不同平台(iOS/Android/Windows)下实际指向的路径也完全不一样。

新手常因为把「文件夹规则」和「平台路径差异」搞混,导致资源加载失败、打包异常这些毛病。这篇就系统地把 Unity 里 6 类核心特殊路径的功能定位、读写权限、访问方式捋清楚,再整理 4 大主流平台(iOS/Android/Windows/Mac)的路径对照表,帮你彻底搞懂 Unity 的路径逻辑,跨平台开发时绕开那些「路径坑」。

一、核心特殊文件夹:规则与用法

Unity 里部分文件夹的名字是「硬编码」的,名字一旦定下来,它的打包行为、使用场景也就固定了。下面按「运行时可用」和「仅编辑器可用」分类说明:

1. StreamingAssets:不压缩的 “原始资源库”

StreamingAssets 是 Unity 专门用来放运行时要读的原始资源(比如配置文件、视频、音频、Lua 脚本)的文件夹,核心特点就是「不压缩、不加密、只读」。

关键规则:

  • 文件夹位置:必须在 Assets 根目录下(路径固定为 Assets/StreamingAssets),在子目录下建是没用的;
  • 打包行为:目录里所有资源会原封不动打进游戏包,不压缩也不加密(资源体积跟原文件一致);
  • 读写权限:只读不可写(运行时改不了也删不了目录里的资源,只能读);
  • 适用场景:放体积大、不用加密的资源(比如游戏开场视频、离线地图数据、JSON 配置文件)。

访问方式:跨平台路径差异

StreamingAssets 的访问必须走 Application.streamingAssetsPath API,但不同平台实际路径格式不一样,得注意适配:

平台访问代码(推荐)实际路径示例(参考)
Unity 编辑器 / Windows/Linux/PS4/Xbox One/SwitchApplication.streamingAssetsPathC:/Project/Assets/StreamingAssets(编辑器) C:/Game/Assets/StreamingAssets(Windows 打包后)
MacOSApplication.streamingAssetsPath/Users/xxx/Game/Contents/Resources/Data/StreamingAssets
iOSApplication.streamingAssetsPath/var/containers/Bundle/Application/xxx/Game.app/Data/Raw
AndroidApplication.streamingAssetsPathjar:file:///data/app/com.xxx.game.apk!/assets

注意事项:

  • Android 平台特殊:StreamingAssets 的资源会打包进 APK 的 assets 目录,得用「流读取」(比如 WWW、UnityWebRequest)来加载,不能直接用文件路径读(像 File.ReadAllText 会失败);
  • 别塞太多小资源:因为不压缩,小资源会白白浪费存储空间,小资源建议用 Resources 或 Addressables 管。

2. Resources:压缩加密的 “动态资源库”

Resources 是 Unity 用来放运行时动态加载资源(比如预制体、图片、音频片段)的文件夹,核心特点是「压缩、加密、只读」。

关键规则:

  • 文件夹位置:灵活,可以在 Assets 根目录或任意子目录下建(比如 Assets/Resources、Assets/GameRes/Resources),只要名字叫 Resources 就行;
  • 打包行为:目录里所有资源会被 Unity 压缩、加密后打进游戏包,而且会自动剔掉「没被引用的资源」(只留被 Resources.Load 调用的);
  • 读写权限:只读不可写(运行时改不了资源,只能加载);
  • 适用场景:放需要动态加载的小资源(比如 UI 预制体、技能特效预制体、角色头像)。

访问方式:无需路径,直接按 “资源名” 加载

Resources 目录下的资源加载不用管实际路径,只需通过 Resources.Load() 方法按「资源相对路径 + 名称」调用(不用带后缀名):

// 示例1:加载 Assets/Resources/UI/Popup.prefab 预制体
GameObject popupPrefab = Resources.Load<GameObject>("UI/Popup");

// 示例2:加载 Assets/GameRes/Resources/Sprites/Avatar.png 图片
Sprite avatarSprite = Resources.Load<Sprite>("Sprites/Avatar");

// 注意:路径不包含 "Resources" 文件夹,也不包含文件后缀名

优缺点:

  • 优点:用起来简单,不用处理跨平台路径差异;资源压缩加密,安全性高;
  • 缺点:资源必须提前打进游戏包,没法动态下载(要热更新得用 Addressables 或第三方框架);打包时所有 Resources 目录会合并,同名资源会冲突。

3. PersistentDataPath:运行时的 “可写数据区”

PersistentDataPath 不是个物理文件夹,而是 Unity 提供的运行时可写路径 API(Application.persistentDataPath),对应设备上的「应用沙盒可写目录」。

关键规则:

  • 路径位置:由系统分配(不同平台路径不同),运行时自动生成(应用装完才存在);
  • 打包行为:不参与游戏包打包,目录是空的,运行时由游戏动态建文件 / 文件夹;
  • 读写权限:可读可写(运行时能建、改、删目录里的文件,是唯一能持久化存数据的路径);
  • 适用场景:放运行时生成的数据(比如玩家存档、下载的热更新资源、截图、日志文件)。

访问方式:跨平台统一 API

不管哪个平台,都直接走 Application.persistentDataPath,不用额外拼路径:

// 示例:在 PersistentDataPath 下创建玩家存档文件
string savePath = Path.Combine(Application.persistentDataPath, "PlayerSave.json");
// 写入存档(可写)
File.WriteAllText(savePath, "{\"level\":10,\"score\":1000}");
// 读取存档(可读)
string saveContent = File.ReadAllText(savePath);

注意事项:

  • 数据持久化:这个目录下的文件在应用卸载前不会被删(就算清应用缓存也不会丢);
  • 跨平台差异:不同平台路径格式不一样(比如 Windows 下在 AppData 目录,iOS 下在 Documents 目录),具体看下文「多平台路径表」。

4. DataPath:应用程序的 “安装目录”

Application.dataPath 指向游戏包的「安装目录」(也就是游戏核心文件所在的目录),核心特点是「只读、路径固定」。

关键规则:

  • 路径含义:对应游戏包的根目录(比如 Windows 下 Game.exe 所在目录,iOS 下的 .app 包目录);
  • 读写权限:只读不可写(运行时改不了目录里的文件,不然会触发系统权限限制);
  • 适用场景:只用来读游戏安装目录下的核心资源(比如 StreamingAssets 目录,需通过 dataPath 拼路径,但推荐直接用 streamingAssetsPath API)。

访问方式:

// 示例:获取应用安装目录路径
string appInstallPath = Application.dataPath;
Debug.Log("应用安装目录:" + appInstallPath);

// (不推荐)拼接 StreamingAssets 路径(建议直接用 Application.streamingAssetsPath)
string streamingPath = Path.Combine(Application.dataPath, "StreamingAssets");

5. Editor:仅编辑器可用的 “工具目录”

Editor 是专门放Unity 编辑器扩展工具的文件夹,核心特点是「不打包、仅编辑器生效」。

关键规则:

  • 文件夹位置:灵活,可以在 Assets 根目录或子目录下建(比如 Assets/Editor、Assets/Tools/Editor);
  • 打包行为:不会被打包进游戏包(只在 Unity 编辑器里能看到,发布后彻底移除);
  • 适用场景:放编辑器脚本(比如自定义 Inspector、打包工具、资源检查器)、编辑器扩展插件(比如 TexturePacker 编辑器插件)。 示例用法:

在 Assets/Editor 下建个 BuildTool.cs 脚本,用来自定义打包流程:

// 该脚本仅在 Unity 编辑器中生效,发布后不包含
using UnityEditor;
using UnityEngine;

public class BuildTool : EditorWindow
{
    [MenuItem("Tools/快速打包 Windows")]
    public static void BuildWindows()
    {
        BuildPipeline.BuildPlayer(
            EditorBuildSettings.scenes,
            "Build/Windows/Game.exe",
            BuildTarget.StandaloneWindows64,
            BuildOptions.None
        );
    }
}

注意:Editor 目录下的脚本必须引用 UnityEditor 命名空间,而且不能包含运行时逻辑(不然打包会报错)。

6. Plugins:第三方 “插件存放区”

Plugins 是用来放第三方插件、SDK、原生代码库的文件夹,核心特点是「自动打包、按平台分类」。

关键规则:

  • 文件夹位置:可以在 Assets 根目录或子目录下建(比如 Assets/Plugins、Assets/SDK/Plugins);
  • 打包行为:目录里的插件会按平台自动打包到对应位置(比如 Android 的 jar/aar 包会进 APK 的 libs 目录,iOS 的 framework 会嵌进 .app 包);
  • 平台分类:支持在 Plugins 下建平台子目录(比如 Plugins/Android、Plugins/iOS),子目录里的插件只在对应平台打包时生效(避免跨平台插件冲突);
  • 适用场景:放第三方 SDK(比如支付 SDK、广告 SDK)、原生平台库(比如 Android 的 jar、iOS 的 .a 静态库)、C++ 插件(.dll/.so)。

示例结构:

Assets/Plugins/
├─ Android/          # 仅 Android 平台生效
│  ├─ libs/          # Android 原生库
│  │  ├─ armeabi-v7a/libgame.so
│  │  └─ arm64-v8a/libgame.so
│  └─ MySDK.aar      # Android SDK 包
├─ iOS/              # 仅 iOS 平台生效
│  └─ MySDK.framework # iOS SDK 框架
└─ Windows/          # 仅 Windows 平台生效
   └─ GamePlugin.dll # Windows 插件

二、多平台路径对照表:4 大主流平台

Application 类提供的 4 个核心路径 API(dataPath、streamingAssetsPath、persistentDataPath、temporaryCachePath)在不同平台下的实际路径差得非常大,是跨平台开发里最容易翻车的地方。下面把 4 大主流平台的路径示例整理出来(注意:示例里的 xxx 是系统自动生成的唯一标识,实际路径以代码打印为准):

1. iOS 平台(沙盒目录)

iOS 应用跑在沙盒里,路径包含系统生成的唯一 UUID,而且 StreamingAssets 对应 Raw 目录:

路径 API实际路径示例(参考)
Application.dataPath/var/containers/Bundle/Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Game.app/Data
Application.streamingAssetsPath/var/containers/Bundle/Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Game.app/Data/Raw
Application.persistentDataPath/var/mobile/Containers/Data/Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Documents
Application.temporaryCachePath/var/mobile/Containers/Data/Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Library/Caches

权限说明:

  • persistentDataPath(Documents 目录):数据会同步到 iCloud(要是开了应用的 iCloud 权限);
  • temporaryCachePath(Caches 目录):系统可能在空间不够时自动清掉,适合放临时文件(比如下载的临时安装包)。

2. Android 平台(APK / 数据目录)

Android 路径分「APK 安装目录」(只读)和「应用数据目录」(可写),StreamingAssets 得通过 APK 流来读:

路径 API实际路径示例(参考)
Application.dataPath/data/app/com.xxx.game-1/base.apk(Android 7.0+) /data/app/com.xxx.game.apk(旧版本)
Application.streamingAssetsPathjar:file:///data/app/com.xxx.game.apk!/assets
Application.persistentDataPath/data/data/com.xxx.game/files
Application.temporaryCachePath/data/data/com.xxx.game/cache

权限说明:

  • dataPath 指向 APK 文件(本质是个压缩包),StreamingAssets 资源在 APK 的 assets 目录里,得用 UnityWebRequest 加载;
  • persistentDataPath 和 temporaryCachePath 在应用私有数据目录里,不用额外权限就能读写(Android 10+ 不用申请存储权限)。

3. Windows 平台(用户目录 / 安装目录)

Windows 路径清楚明了,persistentDataPath 在用户 AppData 目录里,适合放玩家数据:

路径 API实际路径示例(参考)
Application.dataPathC:/Game/Build/Assets(打包后,Game.exe 所在目录的 Assets 子目录) C:/Project/Assets(编辑器中)
Application.streamingAssetsPathC:/Game/Build/Assets/StreamingAssets(打包后) C:/Project/Assets/StreamingAssets(编辑器中)
Application.persistentDataPathC:/Users/张三/AppData/LocalLow/CompanyName/GameName
Application.temporaryCachePathC:/Users/张三/AppData/Local/Temp/CompanyName/GameName

说明:

  • CompanyName 和 GameName 来自 Unity「Player Settings」里的配置(Edit > Project Settings > Player > Product Name);
  • LocalLow 目录是 Windows 用来放「低权限应用数据」的目录,不用管理员权限就能读写。

4. Mac 平台(应用包 / 用户缓存)

Mac 路径跟 Windows 类似,但 dataPath 指向 .app 包内部,persistentDataPath 在用户 Library 目录里:

路径 API实际路径示例(参考)
Application.dataPath/Applications/Game.app/Contents/Assets(打包后,.app 包内部) /Users/张三/Project/Assets(编辑器中)
Application.streamingAssetsPath/Applications/Game.app/Contents/Assets/StreamingAssets(打包后) /Users/张三/Project/Assets/StreamingAssets(编辑器中)
Application.persistentDataPath/Users/张三/Library/Caches/CompanyName/Game Name
Application.temporaryCachePath/private/var/folders/57/6b4_9w8113x2fsmzx_yhrhvh0000gn/T/CompanyName/Game Name

说明:

  • Mac 的 .app 是「伪装成文件的目录」,右键「显示包内容」就能看内部结构(Contents/Assets 对应 dataPath);
  • Library 目录默认隐藏,得按住 Option 键点「前往」菜单才能显示。

三、避坑指南:常见路径问题与解决方案

1. 问题 1:Android 平台 StreamingAssets 资源加载失败

  • 原因:直接用 File.ReadAllText(Application.streamingAssetsPath + “/config.json”) 读资源,忽略了 Android 平台 StreamingAssets 资源的特殊存储方式——Android 下 StreamingAssets 会打包进 APK 的 assets 目录(本质就是压缩包里的文件),没法用普通文件路径读,必须走「流读取」方式加载。
  • 解决方案:用 UnityWebRequest 或 WWW 类(Unity 5.6+ 推荐 UnityWebRequest)以「URL 形式」读,代码示例如下:
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class StreamingAssetsLoader : MonoBehaviour
{
    // 异步读取 StreamingAssets 下的 JSON 配置
    public IEnumerator LoadConfigFromStreamingAssets()
    {
        string configPath = Application.streamingAssetsPath + "/config.json";
        UnityWebRequest request = UnityWebRequest.Get(configPath);

        // 发送请求并等待完成
        yield return request.SendWebRequest();

        // 判断是否读取成功
        if (request.result == UnityWebRequest.Result.Success)
        {
            string configContent = request.downloadHandler.text;
            Debug.Log("配置文件读取成功:" + configContent);
            // 后续解析 JSON 逻辑...
        }
        else
        {
            Debug.LogError("配置文件读取失败:" + request.error);
        }
    }

    // 启动时调用加载
    private void Start()
    {
        StartCoroutine(LoadConfigFromStreamingAssets());
    }
}
  • 注意:这段代码能跨平台用(Windows/Mac/iOS 下 UnityWebRequest 也能读本地文件路径),不用额外判断平台。

2. 问题 2:Resources.Load 加载资源返回 null

  • 常见原因:
  1. 资源路径里带了 Resources 文件夹名(比如写成 Resources.Load(“Resources/UI/Popup”),正确应该是 Resources.Load(“UI/Popup”));
  2. 资源后缀名没省(比如加载图片时写成 Resources.Load<Sprite>(“Sprites/Avatar.png”),正确应该是 Resources.Load<Sprite>(“Sprites/Avatar”));
  3. 资源没放在 Resources 目录下(比如误放 Resource 或 Resources123 目录,名字必须严格是 Resources);
  4. 资源类型不匹配(比如用 Resources.Load<GameObject>() 加载图片资源,应该改成 Resources.Load<Sprite>())。
  • 解决方案:记住「路径不含 Resources、无后缀名、类型匹配」三原则,验证代码示例:
// 正确示例:加载 Assets/GameRes/Resources/Sprites/Avatar.png(Sprite 类型)
Sprite avatar = Resources.Load<Sprite>("Sprites/Avatar");
if (avatar != null)
{
    Debug.Log("图片加载成功");
}
else
{
    Debug.LogError("图片加载失败,检查路径、后缀名、资源类型是否正确");
}

3. 问题 3:PersistentDataPath 下创建文件失败(Android 平台)

  • 原因:
  1. Android 10+ 开了「分区存储」权限限制,直接用 File.Create 建文件时没处理目录不存在的情况(PersistentDataPath 下的子目录得手动建);
  2. 代码里路径拼接用 + 号,忽略了不同平台的路径分隔符(Windows 用 \,Mac/iOS/Android 用 /),导致路径格式错。
  • 解决方案:
  1. 用 Path.Combine 自动处理路径分隔符(跨平台兼容);
  2. 建文件前先检查并建好父目录,代码示例:
using System.IO;
using UnityEngine;

public class PersistentDataWriter : MonoBehaviour
{
    // 向 PersistentDataPath 下的 save 子目录写入存档
    public void WritePlayerSaveData()
    {
        // 1. 用 Path.Combine 拼接路径(跨平台兼容)
        string saveDirPath = Path.Combine(Application.persistentDataPath, "save");
        string saveFilePath = Path.Combine(saveDirPath, "player_save.json");

        // 2. 检查父目录是否存在,不存在则创建
        if (!Directory.Exists(saveDirPath))
        {
            Directory.CreateDirectory(saveDirPath);
            Debug.Log("存档目录创建成功:" + saveDirPath);
        }

        // 3. 写入存档数据
        string saveData = "{\"level\":15,\"hp\":1000,\"gold\":5000}";
        File.WriteAllText(saveFilePath, saveData);
        Debug.Log("存档写入成功:" + saveFilePath);
    }

    private void Start()
    {
        WritePlayerSaveData();
    }
}

4. 问题 4:打包后 Editor 目录下的工具脚本报错

  • 原因:在 Editor 目录下的脚本里写了运行时逻辑(比如 MonoBehaviour 子类),或者没引用 UnityEditor 命名空间却用了编辑器相关 API(比如 EditorUtility),导致打包时 Unity 检测到「编辑器脚本混进运行时代码」就报错了。
  • 解决方案:
  1. Editor 目录下的脚本只用于编辑器工具,别包含任何 MonoBehaviour、Start、Update 这些运行时逻辑;
  2. 所有编辑器相关代码必须放在 UnityEditor 命名空间下,并且在代码顶部加 #if UNITY_EDITOR 宏定义,免得打包时被带进去,示例:
// 正确的 Editor 脚本示例:仅编辑器可用的资源检查工具
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;

// 必须放在 UnityEditor 命名空间下
namespace UnityEditor
{
    public class ResourceChecker : EditorWindow
    {
        // 添加编辑器菜单(仅在 Unity 编辑器中显示)
        [MenuItem("Tools/检查未使用的 Resources 资源")]
        public static void CheckUnusedResources()
        {
            Debug.Log("开始检查未使用的 Resources 资源...");
            // 编辑器资源检查逻辑(如遍历 Resources 目录,判断资源是否被引用)
            // ...
        }
    }
}
#endif

5. 问题 5:多平台打包后 persistentDataPath 路径找不到

  • 原因:开发时习惯打印 Application.persistentDataPath 看路径,但打包后没法直接看设备上的路径,导致没法验证文件是不是真写进去了。
  • 解决方案:
  1. Windows/Mac:直接在代码里打印路径,打包后跑游戏,从日志里复制路径去文件管理器打开(Windows 日志可在 C:/Users/xxx/AppData/LocalLow/CompanyName/GameName/Player.log 看);
  2. Android:通过 ADB 命令看 persistentDataPath 目录,步骤如下:
  • 手机连电脑,开「开发者模式」和「USB 调试」;
  • 打开命令提示符(CMD),输入 adb shell 进手机终端;
  • 输入 cd /data/data/com.xxx.game/files(com.xxx.game 换成你的应用包名),再输入 ls 看目录下的文件;
  1. iOS:通过 Xcode 看沙盒目录,步骤如下:
  • 用 Xcode 打开 Unity 导出的 iOS 项目,连测试设备跑起来;
  • 跑起来后在 Xcode 顶部菜单选 Window > Devices and Simulators;
  • 在设备列表里找到你的应用,点 Download Container 导出沙盒文件;
  • 右键导出的 .xcappdata 文件,选「显示包内容」,进 AppData/Documents 就能看 persistentDataPath 下的文件了。

四、路径管理最佳实践

1. 优先使用 Unity 官方 API,避免硬编码路径

  • 读 StreamingAssets 用 Application.streamingAssetsPath,别手动拼 Application.dataPath + “/StreamingAssets”(免得平台差异出问题);
  • 读可写路径用 Application.persistentDataPath,别硬编码 C:/Users/xxx/AppData/…(保证跨平台兼容)。

2. 封装路径工具类,统一管理路径逻辑

把常用路径的拼接、资源加载逻辑封装成工具类,免得代码里反复写路径拼接和平台判断,示例:

using System.IO;
using UnityEngine;

public static class PathTool
{
    // 1. 获取 StreamingAssets 下资源的完整路径(自动处理路径分隔符)
    public static string GetStreamingAssetsPath(string fileName)
    {
        return Path.Combine(Application.streamingAssetsPath, fileName);
    }

    // 2. 获取 PersistentDataPath 下子目录的完整路径(自动创建目录)
    public static string GetPersistentDataDirPath(string dirName)
    {
        string dirPath = Path.Combine(Application.persistentDataPath, dirName);
        if (!Directory.Exists(dirPath))
        {
            Directory.CreateDirectory(dirPath);
        }
        return dirPath;
    }

    // 3. 获取 PersistentDataPath 下文件的完整路径(自动创建父目录)
    public static string GetPersistentDataFilePath(string dirName, string fileName)
    {
        string dirPath = GetPersistentDataDirPath(dirName);
        return Path.Combine(dirPath, fileName);
    }

    // 4. 简化 Resources 加载(自动处理空值)
    public static T LoadFromResources<T>(string resourcePath) where T : Object
    {
        T resource = Resources.Load<T>(resourcePath);
        if (resource == null)
        {
            Debug.LogError($"Resources 加载失败:路径={resourcePath},类型={typeof(T).Name}");
        }
        return resource;
    }
}
  • 使用示例:
// 读取 StreamingAssets 下的 config.json
string configPath = PathTool.GetStreamingAssetsPath("config.json");

// 写入 PersistentDataPath/save 目录下的 player_save.json
string saveFilePath = PathTool.GetPersistentDataFilePath("save", "player_save.json");
File.WriteAllText(saveFilePath, "存档数据");

// 加载 Resources 下的 UI 预制体
GameObject popupPrefab = PathTool.LoadFromResources<GameObject>("UI/Popup");

3. 区分 “静态资源” 和 “动态资源” 的存储位置

  • 静态资源(打包后不修改的资源,比如配置文件、离线资源):放 StreamingAssets 或 Resources 目录;
  • 动态资源(运行时生成 / 修改的资源,比如玩家存档、下载的更新包、截图):放 Application.persistentDataPath 目录;
  • 临时资源(运行时临时用、可清理的资源,比如下载的临时安装包、缓存图片):放 Application.temporaryCachePath 目录(系统可能自动清)。

4. 多平台测试前,先在编辑器中验证路径逻辑

在 Unity 编辑器里,Application 类的路径 API 会返回编辑器环境下的路径(比如 Application.persistentDataPath 指向 C:/Users/xxx/AppData/LocalLow/CompanyName/GameName),可以先在编辑器里把资源加载、文件读写逻辑测对,再打包到目标平台。

五、总结

Unity 特殊路径的核心逻辑可以概括成「文件夹规则固定,平台路径可变」:

  1. 特殊文件夹(StreamingAssets/Resources/Editor/Plugins)的「打包行为、读写权限」由名字决定,位置和命名规则得严格遵守;
  2. Application 类的路径 API(dataPath/persistentDataPath 这些)在不同平台下实际路径不一样,得靠 API 动态获取,别硬编码;
  3. 跨平台开发的关键是「用统一的 API 访问路径,用适配的方式加载资源」(比如用 UnityWebRequest 读 StreamingAssets,用 Path.Combine 拼路径)。

吃透这篇里的「文件夹规则」「多平台路径表」和「避坑方案」,就能解决 90% 以上的 Unity 路径问题,让资源管理和多平台发布更顺、更稳。