【Unity】安卓端加载素材:实现资源从 StreamingAssets 到 PersistentDataPath 的复制与加载

在 Unity 开发中,StreamingAssets 是一个常用的文件夹,用来存放需要打包到应用程序中的静态文件。但在某些情况下(动态文件的更新和修改,需要读写等),为了支持文件动态读取或修改,资源需要从 StreamingAssets 复制到 PersistentDataPath,再进行加载。

比如我现在是需要将一个电脑端的数字人加载项目放到AR眼镜中,单纯从 StreamingAssets中读取资源在眼镜中无法正常显示,但复制到 PersistentDataPath再动态加载就可以成功显示。

本文将详细介绍如何在执行资源加载之前,将 StreamingAssets 的资源复制到 PersistentDataPath 并正确加载这些资源。本文主要内容包括以下几个部分:

  1. Unity 路径简介StreamingAssetsPersistentDataPath 的区别。
  2. 核心实现步骤:如何在调用资源加载逻辑之前完成复制。
  3. 完整代码示例:实际场景下的完整实现代码。

1. Unity 路径简介

StreamingAssets 文件夹

  • 作用:用于存放静态资源文件,资源会被原封不动地打包到应用程序中。
  • 访问方式
    • PC 平台:通过 Application.streamingAssetsPath 获取路径,可直接访问文件。
    • Android 平台:由于资源被打包在 APK 中,无法直接访问,需使用 UnityWebRequest 或其他方式读取。

PersistentDataPath 文件夹

  • 作用:用于存储动态生成的文件或需要持久化的文件(例如保存文件、日志等)。
  • 访问方式:通过 Application.persistentDataPath 获取路径,可直接读取和写入文件。

2. 核心实现步骤

在调用资源加载逻辑之前,首先需要确保资源已被复制到 PersistentDataPath,并将资源路径更新为新路径。以下是核心步骤:

  1. 复制资源:遍历资源路径,将资源从 StreamingAssets 复制到 PersistentDataPath
  2. 更新路径:将资源路径替换为指向 PersistentDataPath 的新路径。
  3. 加载资源:调用加载逻辑时使用更新后的路径。

3. 实现代码

以下是简化的实现代码,用于展示核心逻辑。

主函数

private mainFunction()
{
    // 获取资源路径
    var basePath = GetBasePath();

    // 定义资源路径
    //PostResult是自定义的类
    var meta = new PostResult
    {
        upload_zzz_url = $"{basePath}/zzz.fbx",
        upload_yyy_url = $"{basePath}/yyy.png",
        upload_xxx_url = new[] { $"{basePath}/xxx1.fbx", $"{basePath}/xxx2.fbx" }
    };

    // 1. 复制资源到 PersistentDataPath
    await CopyAllResourcesToPersistentDataPath(meta);

    // 2. 更新路径为 PersistentDataPath
    UpdateMetaPathsToPersistent(meta);

    // 3. 加载资源
    //实现Load()加载资源的代码
}

步骤 1:复制所有资源到 PersistentDataPath

实现一个方法,将资源路径从 StreamingAssets 复制到 PersistentDataPath。以下为伪代码:

private async UniTask CopyAllResourcesToPersistentDataPath(PostResult meta)
{
	// 定义一个列表来存储所有路径
	List<string> allPaths = new List<string>
	{
	    meta.upload_zzz_url,
	    meta.upload_yyy_url
	};
	allPaths.AddRange(meta.upload_xxx_url);
	
    // 遍历所有路径并逐一复制
    foreach (var path in meta.AllPaths)
    {
        await CopyToPersistentDataPath(path);
    }
}

private async UniTask CopyToPersistentDataPath(string sourcePath)
{
    // 目标路径
    string persistentPath = GetPersistentPath(sourcePath);

    // 如果文件已存在,跳过
    if (FileExists(persistentPath)) return;

	// 判断平台
	if (Application.platform == RuntimePlatform.Android && !sourcePath.Contains("://"))
	{
	    sourcePath = $"file://{sourcePath}"; // Android 平台需要添加前缀
	}
	
    // 使用 UnityWebRequest 从 StreamingAssets 读取文件
	using (UnityWebRequest request = UnityWebRequest.Get(sourcePath))
	{
	    await request.SendWebRequest();

	    if (request.result == UnityWebRequest.Result.Success)
	    {
	        // 将文件写入到 PersistentDataPath
	        File.WriteAllBytes(persistentPath, request.downloadHandler.data);
	    }
	    else
	    {
	        Debug.LogError($"Failed to copy file from {sourcePath} to {persistentPath}: {request.error}");
	    }
	}
}

步骤 2:更新资源路径为 PersistentDataPath

复制完成后,需要更新资源路径为指向 PersistentDataPath

private void UpdateMetaPathsToPersistent(PostResult meta)
{
    // 更新单个路径
    meta.upload_zzz_url = UpdatePathToPersistent(meta.upload_zzz_url);

    // 更新数组路径
    meta.upload_xxx_url = meta.upload_xxx_url.Select(UpdatePathToPersistent).ToArray();
}

private string UpdatePathToPersistent(string sourcePath)
{
    string fileName = Path.GetFileName(sourcePath);
    return Path.Combine(Application.persistentDataPath, fileName);
}
### Unity 支持读取的数据文件类型 在 Unity 开发中,可以通过多种方式读取不同类型的文件数据。以下是常见的可被 Unity 读取的数据文件类型及其处理方法: #### 1. **XML 文件** Unity 可以通过 `XmlDocument` 或其他 XML 解析库来读取 XML 数据文件。通常情况下,在开发阶段可以将 XML 文件放置于 `StreamingAssets` 文件夹中以便调试[^1]。然而需要注意的是,当项目被打包至移动设备时,由于路径差异可能导致无法正常读取文件。因此建议开发者根据目标平台调整文件存储位置。 #### 2. **CSV 文件** 对于 CSV 类型的文件,推荐同样将其置于 `StreamingAssets` 路径下[^2]。这样能够确保无论是在编辑器模式还是构建后的应用中都能正确加载该类资源。具体实现可通过简单的字符串分割逻辑完成解析操作。 #### 3. **JSON 文件** 利用内置工具如 `JsonUtility`,或者第三方插件比如 Newtonsoft.Json (需手动导入),都可以方便地序列化/反序列化 JSON 结构化的对象。下面展示了一个基于官方 API 的例子用于说明如何从 StreamingAssets 加载并转换成 C# 对象实例[^3]: ```csharp using UnityEngine; using System.Collections; public class Example : MonoBehaviour { void Start(){ StartCoroutine(LoadJson()); } IEnumerator LoadJson(){ string filePath = Path.Combine(Application.streamingAssetsPath,"data.json"); UnityWebRequest www = UnityWebRequest.Get(filePath); yield return www.SendWebRequest(); if(www.result != UnityWebRequest.Result.Success){ Debug.LogError($"Failed to load json file:{www.error}"); } else{ MyData data = JsonUtility.FromJson<MyData>(www.downloadHandler.text); // Do something with 'data' } } } [System.Serializable] class MyData{ public int id; public string name; } ``` #### 4. **图片(PNG/JPG)** 和 其他多媒体资产 除了纯文本形式的信息外,图像也是常见的一种静态资源类别之一。如果希望保存截图等内容,则应考虑使用 `Application.persistentDataPath` 来指定实际物理磁盘上的目录作为输出目的地[^4]。此做法适用于 Android 平台以及其他允许外部存储访问的操作系统环境之中。 综上所述,Unity 提供了灵活的方法去管理和交互各种各样的本地或远程数据源,涵盖了结构化文档(xml/json/csv)以及非结构化媒体素材(image/audio/video etc.)等多个方面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值